diff options
author | Jamey Sharp <jamey@minilop.net> | 2010-04-13 12:12:36 -0700 |
---|---|---|
committer | Jamey Sharp <jamey@minilop.net> | 2010-04-13 13:12:07 -0700 |
commit | 405132dab64bf2375f8e57d02b1b53da2311933a (patch) | |
tree | 19d3cb72934225eca65272ed3b3f21da2bd72b82 | |
parent | d3eab4a38f3e53ef21eb3b6fa66ead7afecf6227 (diff) |
Extensions get to filter async errors too.
Apparently I misread XlibInt.c:_XReply and thought that handlers set
with XESetError should be consulted only for the sequence number that
_XReply is currently looking for. In fact, the error handlers are also
consulted when an error arrives for a request that was not expected to
have a reply.
However, in an odd twist, the error handlers are *not* consulted outside
of _XReply--that is, when looking for events, or waiting to be able to
flush the output queue. So this patch takes some small pains to preserve
that behavior, though it seems likely to have been unintentional.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=26545
Signed-off-by: Jamey Sharp <jamey@minilop.net>
-rw-r--r-- | src/xcb_io.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/src/xcb_io.c b/src/xcb_io.c index 96def9f3..7060976d 100644 --- a/src/xcb_io.c +++ b/src/xcb_io.c @@ -114,6 +114,21 @@ static void check_internal_connections(Display *dpy) } } +static int handle_error(Display *dpy, xError *err) +{ + _XExtension *ext; + int ret_code; + /* + * we better see if there is an extension who may + * want to suppress the error. + */ + for(ext = dpy->ext_procs; ext; ext = ext->next) + if(ext->error && (*ext->error)(dpy, err, &ext->codes, &ret_code)) + return ret_code; + _XError(dpy, err); + return 0; +} + static void call_handlers(Display *dpy, xcb_generic_reply_t *buf) { _XAsyncHandler *async, *next; @@ -202,15 +217,25 @@ static void process_responses(Display *dpy, int wait_for_first_event, xcb_generi _XEnq(dpy, (xEvent *) event); wait_for_first_event = 0; } - else if(current_error && event_sequence == current_request) + else if(current_error) { /* This can only occur when called from * _XReply, which doesn't need a new event. */ - *current_error = (xcb_generic_error_t *) event; - event = NULL; - break; + if(event_sequence == current_request) + { + *current_error = (xcb_generic_error_t *) event; + event = NULL; + break; + } + /* Oddly, Xlib only allows extensions to + * suppress errors when those errors + * were seen by _XReply. */ + handle_error(dpy, (xError *) event); } else + /* We're looking for events or flushing + * the output queue. Never suppress + * errors here. */ _XError(dpy, (xError *) event); free(event); event = wait_or_poll_for_event(dpy, wait_for_first_event); @@ -465,8 +490,6 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard) if(error) { - _XExtension *ext; - xError *err = (xError *) error; int ret_code; dpy->last_request_read = error->full_sequence; @@ -500,19 +523,9 @@ Status _XReply(Display *dpy, xReply *rep, int extra, Bool discard) return 0; } - /* - * we better see if there is an extension who may - * want to suppress the error. - */ - for(ext = dpy->ext_procs; ext; ext = ext->next) - if(ext->error && ext->error(dpy, err, &ext->codes, &ret_code)) { - free(error); - return ret_code; - } - - _XError(dpy, err); + ret_code = handle_error(dpy, (xError *) error); free(error); - return 0; + return ret_code; } /* it's not an error, but we don't have a reply, so it's an I/O |