[PATCH xlib] Add support for a display-specific error handler

Jasper St. Pierre jstpierre at mecheye.net
Fri Nov 13 15:24:24 PST 2015


Writing error-safe code that uses Xlib is too obnoxious, and using XCB
is tedious and not performant, as we can't catch events on a giant
stream -- we have to check every operation manually.

In my specific case (writing a GL driver), it would be enough to simply
have a Display-specific error handler, since our driver re-opens the
Display in our own code, but a better approach might be TLS storage for
the global handler.

Signed-off-by: Jasper St. Pierre <jstpierre at mecheye.net>
---
 include/X11/Xlib.h    |  4 ++++
 include/X11/Xlibint.h |  3 +++
 src/ErrHndlr.c        | 15 +++++++++++++++
 src/XlibInt.c         | 12 +++++++++++-
 4 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/include/X11/Xlib.h b/include/X11/Xlib.h
index 2bffa76..772e88c 100644
--- a/include/X11/Xlib.h
+++ b/include/X11/Xlib.h
@@ -1849,6 +1849,10 @@ extern XErrorHandler XSetErrorHandler (
     XErrorHandler	/* handler */
 );
 
+extern XErrorHandler XDisplaySetErrorHandler(
+    Display*            /* display */,
+    XErrorHandler       /* handler */
+);
 
 typedef int (*XIOErrorHandler) (    /* WARNING, this type not in Xlib spec */
     Display*		/* display */
diff --git a/include/X11/Xlibint.h b/include/X11/Xlibint.h
index 4431559..e05792f 100644
--- a/include/X11/Xlibint.h
+++ b/include/X11/Xlibint.h
@@ -205,6 +205,9 @@ struct _XDisplay
 		XGenericEventCookie *	/* in */,
 		XGenericEventCookie *   /* out*/);
 	void *cookiejar;  /* cookie events returned but not claimed */
+
+	/* display-specific error handler */
+	XErrorHandler err_handler;
 };
 
 #define XAllocIDs(dpy,ids,n) (*(dpy)->idlist_alloc)(dpy,ids,n)
diff --git a/src/ErrHndlr.c b/src/ErrHndlr.c
index 167a68b..a8e1eee 100644
--- a/src/ErrHndlr.c
+++ b/src/ErrHndlr.c
@@ -84,3 +84,18 @@ XSetIOErrorHandler(XIOErrorHandler handler)
 
     return (XIOErrorHandler) oldhandler;
 }
+
+XErrorHandler
+XDisplaySetErrorHandler(Display *dpy, XErrorHandler handler)
+{
+    XErrorHandler old_handler;
+#ifdef XTHREADS
+    LockDisplay(dpy);
+#endif
+    old_handler = dpy->err_handler;
+    dpy->err_handler = handler;
+#ifdef XTHREADS
+    UnlockDisplay(dpy);
+#endif
+    return old_handler;
+}
diff --git a/src/XlibInt.c b/src/XlibInt.c
index 80c1298..d720e7b 100644
--- a/src/XlibInt.c
+++ b/src/XlibInt.c
@@ -1387,6 +1387,16 @@ Bool _XDefaultWireError(Display *display, XErrorEvent *he, xError *we)
     return True;
 }
 
+static int
+DispatchDisplayErrorEvent (Display *dpy,
+                           XErrorEvent *event)
+{
+    if (dpy->err_handler)
+        return dpy->err_handler(dpy, event);
+    else
+        return _XErrorFunction(dpy, event);
+}
+
 /*
  * _XError - upcall internal or user protocol error handler
  */
@@ -1426,7 +1436,7 @@ int _XError (
 	    (*dpy->lock->user_lock_display)(dpy);
 	UnlockDisplay(dpy);
 #endif
-	rtn_val = (*_XErrorFunction)(dpy, (XErrorEvent *)&event); /* upcall */
+	rtn_val = DispatchDisplayErrorEvent(dpy, (XErrorEvent *)&event); /* upcall */
 #ifdef XTHREADS
 	LockDisplay(dpy);
 	if (dpy->lock)
-- 
2.4.3



More information about the xorg-devel mailing list