Handle asyncronous X11 errors

Errors for requests sent via Xlib that expect a reply are handled via
XSetErrorHandler(), which sets up a callback function that Xlib calls.
Errors for requests that do not expect a reply or for errors caused via
unchecked XCB requests show up as events of type 0 in the event handling
function.

Before this commit, errors were ignored here. This commit changes the
code so that the errors are printed instead.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2018-09-29 11:11:43 +02:00
parent 3ed73b1f8e
commit 00ae9718ee
1 changed files with 34 additions and 16 deletions

View File

@ -2496,21 +2496,21 @@ root_damaged(session_t *ps) {
} }
/** /**
* Xlib error handler function. * X11 error handler function.
*/ */
static int static void
xerror(Display __attribute__((unused)) *dpy, XErrorEvent *ev) { xerror_common(unsigned long serial, uint8_t major, uint8_t minor, uint8_t error_code) {
session_t * const ps = ps_g; session_t * const ps = ps_g;
int o = 0; int o = 0;
const char *name = "Unknown"; const char *name = "Unknown";
if (should_ignore(ps, ev->serial)) { if (should_ignore(ps, serial)) {
return 0; return;
} }
if (ev->request_code == ps->composite_opcode if (major == ps->composite_opcode
&& ev->minor_code == XCB_COMPOSITE_REDIRECT_SUBWINDOWS) { && minor == XCB_COMPOSITE_REDIRECT_SUBWINDOWS) {
fprintf(stderr, "Another composite manager is already running " fprintf(stderr, "Another composite manager is already running "
"(and does not handle _NET_WM_CM_Sn correctly)\n"); "(and does not handle _NET_WM_CM_Sn correctly)\n");
exit(1); exit(1);
@ -2518,17 +2518,17 @@ xerror(Display __attribute__((unused)) *dpy, XErrorEvent *ev) {
#define CASESTRRET2(s) case s: name = #s; break #define CASESTRRET2(s) case s: name = #s; break
o = ev->error_code - ps->xfixes_error; o = error_code - ps->xfixes_error;
switch (o) { switch (o) {
CASESTRRET2(BadRegion); CASESTRRET2(BadRegion);
} }
o = ev->error_code - ps->damage_error; o = error_code - ps->damage_error;
switch (o) { switch (o) {
CASESTRRET2(XCB_DAMAGE_BAD_DAMAGE); CASESTRRET2(XCB_DAMAGE_BAD_DAMAGE);
} }
o = ev->error_code - ps->render_error; o = error_code - ps->render_error;
switch (o) { switch (o) {
CASESTRRET2(XCB_RENDER_PICT_FORMAT); CASESTRRET2(XCB_RENDER_PICT_FORMAT);
CASESTRRET2(XCB_RENDER_PICTURE); CASESTRRET2(XCB_RENDER_PICTURE);
@ -2539,7 +2539,7 @@ xerror(Display __attribute__((unused)) *dpy, XErrorEvent *ev) {
#ifdef CONFIG_OPENGL #ifdef CONFIG_OPENGL
if (ps->glx_exists) { if (ps->glx_exists) {
o = ev->error_code - ps->glx_error; o = error_code - ps->glx_error;
switch (o) { switch (o) {
CASESTRRET2(GLX_BAD_SCREEN); CASESTRRET2(GLX_BAD_SCREEN);
CASESTRRET2(GLX_BAD_ATTRIBUTE); CASESTRRET2(GLX_BAD_ATTRIBUTE);
@ -2554,7 +2554,7 @@ xerror(Display __attribute__((unused)) *dpy, XErrorEvent *ev) {
#ifdef CONFIG_XSYNC #ifdef CONFIG_XSYNC
if (ps->xsync_exists) { if (ps->xsync_exists) {
o = ev->error_code - ps->xsync_error; o = error_code - ps->xsync_error;
switch (o) { switch (o) {
CASESTRRET2(XSyncBadCounter); CASESTRRET2(XSyncBadCounter);
CASESTRRET2(XSyncBadAlarm); CASESTRRET2(XSyncBadAlarm);
@ -2563,7 +2563,7 @@ xerror(Display __attribute__((unused)) *dpy, XErrorEvent *ev) {
} }
#endif #endif
switch (ev->error_code) { switch (error_code) {
CASESTRRET2(BadAccess); CASESTRRET2(BadAccess);
CASESTRRET2(BadAlloc); CASESTRRET2(BadAlloc);
CASESTRRET2(BadAtom); CASESTRRET2(BadAtom);
@ -2588,17 +2588,32 @@ xerror(Display __attribute__((unused)) *dpy, XErrorEvent *ev) {
print_timestamp(ps); print_timestamp(ps);
{ {
char buf[BUF_LEN] = ""; char buf[BUF_LEN] = "";
XGetErrorText(ps->dpy, ev->error_code, buf, BUF_LEN); XGetErrorText(ps->dpy, error_code, buf, BUF_LEN);
printf("error %4d %-12s request %4d minor %4d serial %6lu: \"%s\"\n", printf("error %4d %-12s request %4d minor %4d serial %6lu: \"%s\"\n",
ev->error_code, name, ev->request_code, error_code, name, major,
ev->minor_code, ev->serial, buf); minor, serial, buf);
} }
// print_backtrace(); // print_backtrace();
}
/**
* Xlib error handler function.
*/
static int
xerror(Display __attribute__((unused)) *dpy, XErrorEvent *ev) {
xerror_common(ev->serial, ev->request_code, ev->minor_code, ev->error_code);
return 0; return 0;
} }
/**
* XCB error handler function.
*/
inline static void
ev_xcb_error(session_t __attribute__((unused)) *ps, xcb_generic_error_t *err) {
xerror_common(err->sequence, err->major_code, err->minor_code, err->error_code);
}
static void static void
expose_root(session_t *ps, XRectangle *rects, int nrects) { expose_root(session_t *ps, XRectangle *rects, int nrects) {
free_all_damage_last(ps); free_all_damage_last(ps);
@ -3268,6 +3283,9 @@ ev_handle(session_t *ps, xcb_generic_event_t *ev) {
case SelectionClear: case SelectionClear:
ev_selection_clear(ps, (xcb_selection_clear_event_t *)ev); ev_selection_clear(ps, (xcb_selection_clear_event_t *)ev);
break; break;
case 0:
ev_xcb_error(ps, (xcb_generic_error_t *)ev);
break;
default: default:
if (ps->shape_exists && ev->response_type == ps->shape_event) { if (ps->shape_exists && ev->response_type == ps->shape_event) {
ev_shape_notify(ps, (xcb_shape_notify_event_t *) ev); ev_shape_notify(ps, (xcb_shape_notify_event_t *) ev);