Keith Packard doesn't seem very responsive (as in 'completely ignoring the subject')
Thank you for persisting, Jonas. On 24 September 2014 21:13, Jonas Petersen <[email protected]> wrote: > By design, on 32-bit systems, the Xlib internal 32-bit request sequence > numbers may wrap. There is some 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. It also contains some > additional optimizations. > > Signed-off-by: Jonas Petersen <[email protected]> > --- > src/Xxcbint.h | 2 +- > src/xcb_io.c | 27 +++++++++++++++++++++------ > 2 files changed, 22 insertions(+), 7 deletions(-) > > diff --git a/src/Xxcbint.h b/src/Xxcbint.h > index bf41c23..feee775 100644 > --- a/src/Xxcbint.h > +++ b/src/Xxcbint.h > @@ -31,7 +31,7 @@ typedef struct _X11XCBPrivate { > char *reply_data; > int reply_length; > int reply_consumed; > - uint64_t last_flushed; > + unsigned long last_flushed; > enum XEventQueueOwner event_owner; > XID next_xid; > > diff --git a/src/xcb_io.c b/src/xcb_io.c > index 5987329..03af1f9 100644 > --- a/src/xcb_io.c > +++ b/src/xcb_io.c > @@ -59,15 +59,19 @@ static void require_socket(Display *dpy) > { > if(dpy->bufmax == dpy->buffer) > { > - uint64_t sent; > + uint64_t sent64; > + unsigned long sent; > int flags = 0; > /* if we don't own the event queue, we have to ask XCB > * to set our errors aside for us. */ > if(dpy->xcb->event_owner != XlibOwnsEventQueue) > flags = XCB_REQUEST_CHECKED; > if(!xcb_take_socket(dpy->xcb->connection, return_socket, > dpy, > - flags, &sent)) > + flags, &sent64)) > _XIOError(dpy); > + > + sent = sent64; > + > /* Xlib uses unsigned long for sequence numbers. XCB > * uses 64-bit internally, but currently exposes an > * unsigned int API. If these differ, Xlib cannot track > @@ -77,7 +81,7 @@ static void require_socket(Display *dpy) > * 64-bit sequence numbers. */ > if (sizeof(unsigned long) > sizeof(unsigned int) && > dpy->xcb->event_owner == XlibOwnsEventQueue && > - (sent - dpy->last_request_read >= (UINT64_C(1) << > 32))) { > + (long) (sent - dpy->last_request_read) < 0) { > throw_thread_fail_assert("Sequence number wrapped " > "beyond 32 bits while > Xlib " > "did not own the socket", > @@ -455,7 +459,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 +468,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 +482,14 @@ 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 = (uint64_t) dpy->xcb->last_flushed + 1; > sequence <= unwrapped_request; ++sequence) > + /* On systems where unsigned long is 32 bits, the > 64-bit sequence > + * passed to append_pending_request might get > trimmed off. > + * This is logically correct and expected, as it's > simply > + * 're-wrapping' the 'unwrapped' sequence number. > */ > 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.9.1 > > _______________________________________________ > [email protected]: X.Org development > Archives: http://lists.x.org/archives/xorg-devel > Info: http://lists.x.org/mailman/listinfo/xorg-devel > -- Life is complex, it has a real part and an imaginary part.
_______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
