[Xcb] [PATCH libxcb 4/4] send_fds(): Handle too many outstanding requests

Uli Schlachter psychon at znc.in
Thu May 14 00:55:35 PDT 2015


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 FD 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 at znc.in>
---
 src/xcb_out.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/src/xcb_out.c b/src/xcb_out.c
index 06fae4c..37fd16d 100644
--- a/src/xcb_out.c
+++ b/src/xcb_out.c
@@ -187,11 +187,17 @@ static void send_fds(xcb_connection_t *c, unsigned int num_fds, int *fds)
 {
 #if HAVE_SENDMSG
     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) {
             _xcb_out_flush_to(c, c->out.request);
             if (c->has_error)
                 break;
+
+            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;
+            }
         }
         if (!c->has_error)
             c->out.out_fd.fd[c->out.out_fd.nfd++] = fds[0];
@@ -296,6 +302,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, num_fds, fds);
+
     prepare_socket_request(c);
 
     /* send GetInputFocus (sync_req) when 64k-2 requests have been sent without
@@ -304,7 +315,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)
     {
@@ -312,7 +323,6 @@ uint64_t xcb_send_request_with_fds64(xcb_connection_t *c, int flags, struct iove
         prepare_socket_request(c);
     }
 
-    send_fds(c, num_fds, fds);
     send_request(c, req->isvoid, workaround, flags, vector, veclen);
     request = c->has_error ? 0 : c->out.request;
     pthread_mutex_unlock(&c->iolock);
-- 
2.1.4



More information about the Xcb mailing list