Discussion:
[Xcb] How to properly discard socket-handoff GetInputFocus requests?
Clemens Eisserer
2018-02-17 16:36:14 UTC
Permalink
Hi,

The documentation for xcb_take_socket states xcb expectes the first
request of an external socket owner after taking the socket to be a
GetInputFocus request:

* This means that the first request you send after xcb_take_socket must cause a
* reply (e.g. just insert a GetInputFocus request).....You do not have
to wait for
* any of the GetInputFocus replies, but can instead handle them via
* xcb_discard_reply().

However, for both - xcb_discard_reply as well as xcb_discard_reply64 -
it is stated in the documentation, that they are not suited for
replies for requests not generated by xcb itself:

* Note that the sequence really does have to come from an xcb cookie;
* this function is not designed to operate on socket-handoff replies.

So, how can I properly discard the GetInputFocus replies?

Thanks and best regards, Clemens
Uli Schlachter
2018-02-24 08:31:07 UTC
Permalink
Post by Clemens Eisserer
Hi,
The documentation for xcb_take_socket states xcb expectes the first
request of an external socket owner after taking the socket to be a
* This means that the first request you send after xcb_take_socket must cause a
* reply (e.g. just insert a GetInputFocus request).....You do not have
to wait for
* any of the GetInputFocus replies, but can instead handle them via
* xcb_discard_reply().
However, for both - xcb_discard_reply as well as xcb_discard_reply64 -
it is stated in the documentation, that they are not suited for
* Note that the sequence really does have to come from an xcb cookie;
* this function is not designed to operate on socket-handoff replies.
So, how can I properly discard the GetInputFocus replies?
Uhm. I do not know, looking at the code and what Xlib does ended up
confusing me some more. Right now I see no reason why
xcb_discard_reply() would not work, but I haven't really checked this
properly.

How are you handling other replies that the requests that you send
generate? Can't you generate the GetInputFocus reply the same way?

Also, why do you need to take the socket at all? Can't you just use xcb
"the way it is intended to be used"?

Cheers,
Uli
--
Bruce Schneier can read and understand Perl programs.
Clemens Eisserer
2018-02-25 07:05:45 UTC
Permalink
Hi Uli,
Post by Uli Schlachter
Uhm. I do not know, looking at the code and what Xlib does ended up
confusing me some more. Right now I see no reason why
xcb_discard_reply() would not work, but I haven't really checked this
properly.
The issue is - I don't know of any way to get the sequence number
using official APIs.
So I can't actually call xcb_discard_reply.

I wonder, would it be sufficient to call
xcb_discard_reply(xcb_get_input_focus(xcbCon).sequence) right before I
take the socket unconditionally and make sure I cause a
socket-revocation (e.g. calling XNoOp()) before approaching the 16-bit
unsigned int sequence number wrap arround?

Or does the xcb code really expect the first request *after* socket
handoff to cause a reply?
Post by Uli Schlachter
How are you handling other replies that the requests that you send
generate? Can't you generate the GetInputFocus reply the same way?
I don't generate requests in protocol generated during I own the socket.
Post by Uli Schlachter
Also, why do you need to take the socket at all? Can't you just use xcb
"the way it is intended to be used"?
I use socket handoff for batching certain operations of a immediate
rendering API (Java2D).

Socket handoff allows me to control:
* when protocol is submitted to the x-server (whereas when using
native xcb/xlib APIs this is an implementation detail I don't have
control over)
* modification of queued commands right before they are sent

To allow for that batching, I need both features.
So the need to generate protocol myself is actually a side-effect, not
the reason I use it.

Thanks & best regards, Clemens
Uli Schlachter
2018-02-25 17:45:37 UTC
Permalink
Post by Clemens Eisserer
Hi Uli,
Post by Uli Schlachter
Uhm. I do not know, looking at the code and what Xlib does ended up
confusing me some more. Right now I see no reason why
xcb_discard_reply() would not work, but I haven't really checked this
properly.
The issue is - I don't know of any way to get the sequence number
using official APIs.
So I can't actually call xcb_discard_reply.
The last argument to xcb_take_socket gives you the sequence number. It
is just the number of requests that were sent on the connection. So the
sequence number of the first request that you generate on your own is
<that number> + 1, etc.
Post by Clemens Eisserer
I wonder, would it be sufficient to call
xcb_discard_reply(xcb_get_input_focus(xcbCon).sequence) right before I
take the socket unconditionally and make sure I cause a
socket-revocation (e.g. calling XNoOp()) before approaching the 16-bit
unsigned int sequence number wrap arround?
Sure, but I'd use xcb_discard_reply(xcb_get_input_focus(connection))
instead of XNoOp(). :-)
Post by Clemens Eisserer
Or does the xcb code really expect the first request *after* socket
handoff to cause a reply?
Well, not really. Xcb just has to see a reply or an error every 2^16
(possibly 2^16-1, I'm not quite sure) requests to detect the sequence
number wrap-around correctly. Since you do not know how far away the
last request causing a reply was when xcb_take_socket() is called, there
is a possibility that a wrap-around happens next if you do not send a
request causing a reply.

Hence, the rule of "the first request has to cause a reply" is mostly
just a safe over-approximation over some internal information that xcb
does not hand out.
Post by Clemens Eisserer
Post by Uli Schlachter
How are you handling other replies that the requests that you send
generate? Can't you generate the GetInputFocus reply the same way?
I don't generate requests in protocol generated during I own the socket.
Post by Uli Schlachter
Also, why do you need to take the socket at all? Can't you just use xcb
"the way it is intended to be used"?
I use socket handoff for batching certain operations of a immediate
rendering API (Java2D).
* when protocol is submitted to the x-server (whereas when using
native xcb/xlib APIs this is an implementation detail I don't have
control over)
* modification of queued commands right before they are sent
To allow for that batching, I need both features.
So the need to generate protocol myself is actually a side-effect, not
the reason I use it.
So... why don't you just batch things outside of xcb (in a similar way
as you do know) and then use e.g. xcb_send_request() to send the
resulting requests when you really want to? Or alternatively, batch them
as you do know and then use the normal wrapper functions provided by xcb
to send the request? Why do you need to take the socket to batch requests?

Google gave me
http://hg.openjdk.java.net/xrender/xrender/jdk/rev/0522a2e793b2 at which
point there is too much code for me to quickly understand. At least I
see that Java_sun_java2d_xr_XRBackendJava_takeSocket ignores the "sent"
variable that would provide it with sequence numbers.

(In case the answer is "I am trying to emulate XLockDisplay()", my next
question will be: why? What bad things would happen if another thread
would use the xcb connection at the same time?)
(Also, my reaction would likely contain "noooooooo!!")

Cheers,
Uli

P.S.: The second Google result is
http://xcb.pdx.freedesktop.narkive.com/0tzlcsB1/questions-about-xcb-writev-and-socket-handoff
from 9 years ago :-)
--
Bruce Schneier can read and understand Perl programs.
Clemens Eisserer
2018-02-26 08:07:00 UTC
Permalink
Hi Uli,
Post by Uli Schlachter
The last argument to xcb_take_socket gives you the sequence number. It
is just the number of requests that were sent on the connection. So the
sequence number of the first request that you generate on your own is
<that number> + 1, etc.
Strange, I tried calling xcb_discard_reply64(sent + 1) and it didn't work.
Post by Uli Schlachter
Hence, the rule of "the first request has to cause a reply" is mostly
just a safe over-approximation over some internal information that xcb
does not hand out.
Good to know, thanks for the confirmation.
I now implemented issuing xcb_get_input_focus right before requesting
the socket and it seems to work fine.
Post by Uli Schlachter
So... why don't you just batch things outside of xcb (in a similar way
as you do know) and then use e.g. xcb_send_request() to send the
resulting requests when you really want to? Or alternatively, batch them
as you do know and then use the normal wrapper functions provided by xcb
to send the request? Why do you need to take the socket to batch requests?
The most important aspect is maintenance.
I only work on a tiny fraction of the whole Java/X11 code - there are
tons of other code around, sometimes legacy stuff which is better not
touched.

If I would do batching myself, I would have to find all the right
spots where/when to flush my buffers / end a batch.
XCBs socket handoff is beneath all that, so whoever calls into Xlib, I
am notified and can properly clean up.
Post by Uli Schlachter
Google gave me
http://hg.openjdk.java.net/xrender/xrender/jdk/rev/0522a2e793b2 at which
point there is too much code for me to quickly understand. At least I
see that Java_sun_java2d_xr_XRBackendJava_takeSocket ignores the "sent"
variable that would provide it with sequence numbers.
I remember :)
Back then the goal was to avoid Java->C interface overhead, however
this didn't work out - and the batching idea was not on my radar.

Thanks again for the confirmation and best regards, Clemens
Uli Schlachter
2018-03-03 09:15:49 UTC
Permalink
Post by Clemens Eisserer
Hi Uli,
Post by Uli Schlachter
The last argument to xcb_take_socket gives you the sequence number. It
is just the number of requests that were sent on the connection. So the
sequence number of the first request that you generate on your own is
<that number> + 1, etc.
Strange, I tried calling xcb_discard_reply64(sent + 1) and it didn't work.
How do you determine that? It seems to work for me (see the attached
program which sends two GetInputFocus requests via xcb_writev() and
discards the first reply, then uses xcb_poll_for_reply64() to test if
this really worked).

Cheers,
Uli
--
"Do you know that books smell like nutmeg or some spice from a foreign
land?"
-- Faber in Fahrenheit 451
Loading...