By design, on 32-bit systems, the Xlib internal 32-bit request sequence
numbers may wrap. There is two locations within xcb_io.c that are not
wrap-safe though. The value of last_flushed relies on request to be
sequential all the time. This is not given in the moment when the sequence
has just wrapped. Applications may then crash with a "Fatal IO error 11
(Resource temporarily unavailable)".

This patch fixes this by "unwrapping" the sequence number when needed to
retain the sequence relative to last_flushed.

Signed-off-by: Jonas Petersen <[email protected]>
---
 src/xcb_io.c |   13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/xcb_io.c b/src/xcb_io.c
index 727c6c7..34ca46e 100644
--- a/src/xcb_io.c
+++ b/src/xcb_io.c
@@ -455,7 +455,7 @@ void _XSend(Display *dpy, const char *data, long size)
        static const xReq dummy_request;
        static char const pad[3];
        struct iovec vec[3];
-       uint64_t requests;
+       uint64_t requests, unwrapped_request;
        _XExtension *ext;
        xcb_connection_t *c = dpy->xcb->connection;
        if(dpy->flags & XlibDisplayIOError)
@@ -464,6 +464,13 @@ void _XSend(Display *dpy, const char *data, long size)
        if(dpy->bufptr == dpy->buffer && !size)
                return;
 
+       unwrapped_request = dpy->request;
+       /* If there was a sequence number wrap since our last flush,
+        * make sure the sequence number we use, stays in sequence
+        * with dpy->xcb->last_flush. */
+       if (sizeof(uint64_t) > sizeof(unsigned long) && dpy->request < 
dpy->xcb->last_flushed)
+               unwrapped_request += UINT64_C(1) << 32;
+
        /* iff we asked XCB to set aside errors, we must pick those up
         * eventually. iff there are async handlers, we may have just
         * issued requests that will generate replies. in either case,
@@ -471,10 +478,10 @@ void _XSend(Display *dpy, const char *data, long size)
        if(dpy->xcb->event_owner != XlibOwnsEventQueue || dpy->async_handlers)
        {
                uint64_t sequence;
-               for(sequence = dpy->xcb->last_flushed + 1; sequence <= 
dpy->request; ++sequence)
+               for(sequence = dpy->xcb->last_flushed + 1; sequence <= 
unwrapped_request; ++sequence)
                        append_pending_request(dpy, sequence);
        }
-       requests = dpy->request - dpy->xcb->last_flushed;
+       requests = unwrapped_request - dpy->xcb->last_flushed;
        dpy->xcb->last_flushed = dpy->request;
 
        vec[0].iov_base = dpy->buffer;
-- 
1.7.10.4

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to