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 <[email protected]>
---
 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

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to