Re: Help with external socket handling and xcb
Uli Schlachter <[email protected]> Mon, 20 Sep 2021 16:00:03 +0200
| Newsgroups | gmane.comp.freedesktop.xcb |
|---|---|
| Message-ID | <[email protected]> |
Hi, my mail program just informed me that there are new mails in my "xcb" folder. No idea why it needed ten days to do so. Sorry! Uhm. There is a lot going on in your mail. I'll skip all the "I wish things where like XYZ", because I don't really know what to answer to that. Sorry, but things are not like that currently. Am 09.09.21 um 12:48 schrieb Carlo Wood: [...] >>> So, since it doesn't do that (as far as I know), it will have to >>> make sure that every time it has something to write, it writes >>> ALL of it before returning to my code... and that sounds very >>> blocking. How can this ever work reliable with a non-blocking >>> fd? Or is xcb just calling write in a loop until it wrote everything >>> it has to write (also when write returns EAGAIN)? >> >> Basically yes. _xcb_conn_wait() calls write_vec() to write some data >> whenever poll()/select() say that the FD is writeable and there is >> some pending data to send. Here is the loop that then calls >> _xcb_conn_wait() until everything was written: >> https://github.com/freedesktop/xcb-libxcb/blob/ee9dfc9a7658e7fe75d27483bb5ed1ba4d1e2c86/src/xcb_out.c#L457-L458 > > Just to be clear; so this means that in order for xcb_poll_for_event > to work while only calling it when I see that the fd is readable, I only > ever have to monitor that the fd is readable, and never have to worry > about monitoring if the fd is writable, because all writing is done > blocking, even though the fd itself is non-blocking? Yup. You just monitor the FD for readability and then you can use xcb_poll_for_event() / xcb_poll_for_reply() to check for "what is going on". There is also xcb_poll_for_event_queued() which only checks the internal buffer, but does not try to read anything from the socket. But beware: Any XCB function can read from the socket. Even sending a request may read from the socket (this is necessary to avoid a deadlock with the X11 server). Thus, you should "pretend" that the socket is readable after you wrote anything and call xcb_poll_for_event() / xcb_poll_for_reply() afterwards. > >> >>> If anyone can give me pointers, or maybe tell me about a part of >>> the API that I missed that is suitable for this, that would be >>> great! >> >> For non-blockingly waiting for a reply to a request: Do you know about >> xcb_poll_for_reply()? There is an example on how to use that to get a >> callback-based "your reply arrived"-API here: >> https://gitlab.freedesktop.org/xorg/lib/libxcb/-/issues/52#note_712068 >> (Hm, it seems like this code does not handle sequence number >> overflows...) > > Hmm. This is still polling in nature and hard to wrap my head around > without knowing more about the protocol that is being sent to and from > the X server. If you want to know more about the protocol and want to know how to identify individual packages: - Stuff being sent to the server has a length field in bytes 3/4 of the packet. This is the number of four-byte-units of the packet. - There is an extension for "big requests". In this case, the package length will be zero and the following four bytes form a 32 bit length field. - Stuff being received from the server always has at least 32 bytes. - The first byte of a packet is its response_type - Errors have response_type 0 and are always 32 bytes large - Replies have response_type 1 and xcb_generic_reply_t describes their layout. The length field is the number-of-four-byte-quantities-after-the-32-bytes. So, a reply has length 32 + 4*((xcb_generic_reply_t*)r)->length - Events always have 32 bytes - Except that this turned out not to be enough and the X11 generic events extension was born. These events have response_type=35 and again contain a length field (see xcb_ge_generic_event_t) See here: https://github.com/freedesktop/xcb-libxcb/blob/ee9dfc9a7658e7fe75d27483bb5ed1ba4d1e2c86/src/xcb_in.c#L236-L254 > Really non-polling would be when a callback for arrived replies is done > whenever the function that reads incoming data (called by my > application when there is data to read on the fd) sees that such > replies did arrive. Okay, then when the socket is readable, you do something like dispatch_replies(conn, 1) from the code here: https://gitlab.freedesktop.org/xorg/lib/libxcb/-/issues/52#note_712068 Additionally, you use xcb_poll_for_event() to check if an event was received. > I could call "poll_for_reply" whenever the socket becomes readable, but > that makes no sense because at that moment the socket hasn't been read > yet. Both xcb_poll_for_event() and xcb_poll_for_reply() will try to read from the socket when: - there is no pending event/reply in the buffer and - no other thread is currently trying to read from the socket xcb_poll_for_queued_event() skips the "try to read from the socket"-part. It was added because this unconditional trying to read from the socket caused slowdowns with libX11. There is no xcb_poll_for_queued_reply() currently. Cheers & again sorry for the slow answer, Uli -- - He wants the impossible...! - That's the short definition of 'captain'.