<div dir="ltr"><div><br></div>Keith Packard doesn't seem very responsive (as in 'completely ignoring the subject')<br><div><br>Thank you for persisting, Jonas.<br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On 24 September 2014 21:13, Jonas Petersen <span dir="ltr"><<a href="mailto:jnsptrsn1@gmail.com" target="_blank">jnsptrsn1@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">By design, on 32-bit systems, the Xlib internal 32-bit request sequence<br>
numbers may wrap. There is some locations within xcb_io.c that are not<br>
wrap-safe though. The value of last_flushed relies on request to be<br>
sequential all the time. This is not given in the moment when the<br>
sequence has just wrapped. Applications may then crash with a<br>
"Fatal IO error 11 (Resource temporarily unavailable)".<br>
<br>
This patch fixes this by "unwrapping" the sequence number when needed to<br>
retain the sequence relative to last_flushed. It also contains some<br>
additional optimizations.<br>
<br>
Signed-off-by: Jonas Petersen <<a href="mailto:jnsptrsn1@gmail.com">jnsptrsn1@gmail.com</a>><br>
---<br>
 src/Xxcbint.h |  2 +-<br>
 src/xcb_io.c  | 27 +++++++++++++++++++++------<br>
 2 files changed, 22 insertions(+), 7 deletions(-)<br>
<br>
diff --git a/src/Xxcbint.h b/src/Xxcbint.h<br>
index bf41c23..feee775 100644<br>
--- a/src/Xxcbint.h<br>
+++ b/src/Xxcbint.h<br>
@@ -31,7 +31,7 @@ typedef struct _X11XCBPrivate {<br>
        char *reply_data;<br>
        int reply_length;<br>
        int reply_consumed;<br>
-       uint64_t last_flushed;<br>
+       unsigned long last_flushed;<br>
        enum XEventQueueOwner event_owner;<br>
        XID next_xid;<br>
<br>
diff --git a/src/xcb_io.c b/src/xcb_io.c<br>
index 5987329..03af1f9 100644<br>
--- a/src/xcb_io.c<br>
+++ b/src/xcb_io.c<br>
@@ -59,15 +59,19 @@ static void require_socket(Display *dpy)<br>
 {<br>
        if(dpy->bufmax == dpy->buffer)<br>
        {<br>
-               uint64_t sent;<br>
+               uint64_t sent64;<br>
+               unsigned long sent;<br>
                int flags = 0;<br>
                /* if we don't own the event queue, we have to ask XCB<br>
                 * to set our errors aside for us. */<br>
                if(dpy->xcb->event_owner != XlibOwnsEventQueue)<br>
                        flags = XCB_REQUEST_CHECKED;<br>
                if(!xcb_take_socket(dpy->xcb->connection, return_socket, dpy,<br>
-                                   flags, &sent))<br>
+                                   flags, &sent64))<br>
                        _XIOError(dpy);<br>
+<br>
+               sent = sent64;<br>
+<br>
                /* Xlib uses unsigned long for sequence numbers.  XCB<br>
                 * uses 64-bit internally, but currently exposes an<br>
                 * unsigned int API.  If these differ, Xlib cannot track<br>
@@ -77,7 +81,7 @@ static void require_socket(Display *dpy)<br>
                 * 64-bit sequence numbers. */<br>
                if (sizeof(unsigned long) > sizeof(unsigned int) &&<br>
                    dpy->xcb->event_owner == XlibOwnsEventQueue &&<br>
-                   (sent - dpy->last_request_read >= (UINT64_C(1) << 32))) {<br>
+                   (long) (sent - dpy->last_request_read) < 0) {<br>
                        throw_thread_fail_assert("Sequence number wrapped "<br>
                                                 "beyond 32 bits while Xlib "<br>
                                                 "did not own the socket",<br>
@@ -455,7 +459,7 @@ void _XSend(Display *dpy, const char *data, long size)<br>
        static const xReq dummy_request;<br>
        static char const pad[3];<br>
        struct iovec vec[3];<br>
-       uint64_t requests;<br>
+       uint64_t requests, unwrapped_request;<br>
        _XExtension *ext;<br>
        xcb_connection_t *c = dpy->xcb->connection;<br>
        if(dpy->flags & XlibDisplayIOError)<br>
@@ -464,6 +468,13 @@ void _XSend(Display *dpy, const char *data, long size)<br>
        if(dpy->bufptr == dpy->buffer && !size)<br>
                return;<br>
<br>
+       unwrapped_request = dpy->request;<br>
+       /* If there was a sequence number wrap since our last flush,<br>
+        * make sure the sequence number we use, stays in sequence<br>
+        * with dpy->xcb->last_flush. */<br>
+       if (sizeof(uint64_t) > sizeof(unsigned long) && dpy->request < dpy->xcb->last_flushed)<br>
+               unwrapped_request += UINT64_C(1) << 32;<br>
+<br>
        /* iff we asked XCB to set aside errors, we must pick those up<br>
         * eventually. iff there are async handlers, we may have just<br>
         * issued requests that will generate replies. in either case,<br>
@@ -471,10 +482,14 @@ void _XSend(Display *dpy, const char *data, long size)<br>
        if(dpy->xcb->event_owner != XlibOwnsEventQueue || dpy->async_handlers)<br>
        {<br>
                uint64_t sequence;<br>
-               for(sequence = dpy->xcb->last_flushed + 1; sequence <= dpy->request; ++sequence)<br>
+               for(sequence = (uint64_t) dpy->xcb->last_flushed + 1; sequence <= unwrapped_request; ++sequence)<br>
+                       /* On systems where unsigned long is 32 bits, the 64-bit sequence<br>
+                        * passed to append_pending_request might get trimmed off.<br>
+                        * This is logically correct and expected, as it's simply<br>
+                        * 're-wrapping' the 'unwrapped' sequence number. */<br>
                        append_pending_request(dpy, sequence);<br>
        }<br>
-       requests = dpy->request - dpy->xcb->last_flushed;<br>
+       requests = unwrapped_request - dpy->xcb->last_flushed;<br>
        dpy->xcb->last_flushed = dpy->request;<br>
<br>
        vec[0].iov_base = dpy->buffer;<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.9.1<br>
<br>
_______________________________________________<br>
<a href="mailto:xorg-devel@lists.x.org">xorg-devel@lists.x.org</a>: X.Org development<br>
Archives: <a href="http://lists.x.org/archives/xorg-devel" target="_blank">http://lists.x.org/archives/xorg-devel</a><br>
Info: <a href="http://lists.x.org/mailman/listinfo/xorg-devel" target="_blank">http://lists.x.org/mailman/listinfo/xorg-devel</a><br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br>Life is complex, it has a real part and an imaginary part.
</div>