diff options
author | Uli Schlachter <psychon@znc.in> | 2015-05-14 09:44:05 +0200 |
---|---|---|
committer | Uli Schlachter <psychon@znc.in> | 2015-06-12 09:39:13 +0200 |
commit | 8584c0e09573a29d8ba7050e3d5afd925b4d8d80 (patch) | |
tree | e76366469697d16bbc79881ac605d5d41dde5f07 /src | |
parent | 658fb4a5f0050db68fdf092936afe596412ef5f7 (diff) |
send_fds(): Handle too many outstanding FDs to send
Before this patch, the following code caused an endless loop in send_fds(),
because the queue of FDs to send was eventually full, but _xcb_out_flush_to()
didn't make any progress, since there was no request to send:
while (1) { xcb_send_fd(conn, dup(some_fd)); }
Fix this by sending a sync when flushing didn't make any progress. That way we
actually have something to send and can attach the pending FDs.
Because send_fds() can now send requests, the code in
xcb_send_request_with_fds64() has to be changed. It has to call send_fds()
before it establishes a good sequence number for the request it wants to send.
Signed-off-by: Uli Schlachter <psychon@znc.in>
Diffstat (limited to 'src')
-rw-r--r-- | src/xcb_out.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/src/xcb_out.c b/src/xcb_out.c index b5b6f34..3601a5f 100644 --- a/src/xcb_out.c +++ b/src/xcb_out.c @@ -196,12 +196,16 @@ static void send_fds(xcb_connection_t *c, int *fds, unsigned int num_fds) prepare_socket_request(c); while (num_fds > 0) { - /* FIXME: This will busy-loop when XCB_MAX_PASS_FD fds are sent at once */ while (c->out.out_fd.nfd == XCB_MAX_PASS_FD && !c->has_error) { /* XXX: if c->out.writing > 0, this releases the iolock and * potentially allows other threads to interfere with their own fds. */ _xcb_out_flush_to(c, c->out.request); + + if (c->out.out_fd.nfd == XCB_MAX_PASS_FD) { + /* We need some request to send FDs with */ + _xcb_out_send_sync(c); + } } if (c->has_error) break; @@ -306,6 +310,11 @@ uint64_t xcb_send_request_with_fds64(xcb_connection_t *c, int flags, struct iove /* get a sequence number and arrange for delivery. */ pthread_mutex_lock(&c->iolock); + /* send FDs before establishing a good request number, because this might + * call send_sync(), too + */ + send_fds(c, fds, num_fds); + prepare_socket_request(c); /* send GetInputFocus (sync_req) when 64k-2 requests have been sent without @@ -314,7 +323,7 @@ uint64_t xcb_send_request_with_fds64(xcb_connection_t *c, int flags, struct iove * applications see sequence 0 as that is used to indicate * an error in sending the request */ - + while ((req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2) || (unsigned int) (c->out.request + 1) == 0) { @@ -322,7 +331,6 @@ uint64_t xcb_send_request_with_fds64(xcb_connection_t *c, int flags, struct iove prepare_socket_request(c); } - send_fds(c, fds, num_fds); send_request(c, req->isvoid, workaround, flags, vector, veclen); request = c->has_error ? 0 : c->out.request; pthread_mutex_unlock(&c->iolock); |