summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2019-06-14 17:55:14 +0200
committerCarlos Garnacho <carlosg@gnome.org>2020-10-15 11:14:53 +0200
commit9f9c5365816bdd036fd80d54b22e86764ea4b7a7 (patch)
treefc1ed95b7455c5af6787219aef2c0b2acbdbfbac
parent4cb758019e374fa7c022fe79d28444e13441717b (diff)
Add XSetIOErrorExitHandler() function
This function complements XSetIOErrorHandler(), allowing to override the default behavior that trusts on I/O errors never coming back (i.e. exit()ing the process). This is meant as a mechanism for Wayland compositors (that are too a X11 client + compositing manager) to unfasten seatbelts and jump through the car window. It might get lucky and land on a stack of pillows. In consequence, some functions labeled as _X_NORETURN can as a matter of fact return. So those hints were removed. Signed-off-by: Carlos Garnacho <carlosg@gnome.org> Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
-rw-r--r--include/X11/Xlib.h10
-rw-r--r--include/X11/Xlibint.h9
-rw-r--r--man/XSetErrorHandler.man12
-rw-r--r--src/ErrHndlr.c25
-rw-r--r--src/OpenDis.c2
-rw-r--r--src/XlibInt.c18
6 files changed, 70 insertions, 6 deletions
diff --git a/include/X11/Xlib.h b/include/X11/Xlib.h
index 736ee1cb..65f81492 100644
--- a/include/X11/Xlib.h
+++ b/include/X11/Xlib.h
@@ -1858,6 +1858,16 @@ extern XIOErrorHandler XSetIOErrorHandler (
XIOErrorHandler /* handler */
);
+typedef void (*XIOErrorExitHandler) ( /* WARNING, this type not in Xlib spec */
+ Display*, /* display */
+ void* /* user_data */
+);
+
+extern void XSetIOErrorExitHandler (
+ Display*, /* display */
+ XIOErrorExitHandler, /* handler */
+ void* /* user_data */
+);
extern XPixmapFormatValues *XListPixmapFormats(
Display* /* display */,
diff --git a/include/X11/Xlibint.h b/include/X11/Xlibint.h
index 3303813e..8b43d3b7 100644
--- a/include/X11/Xlibint.h
+++ b/include/X11/Xlibint.h
@@ -205,6 +205,9 @@ struct _XDisplay
/* avoid recursion on requests sequence number synchronization */
Bool req_seq_syncing; /* requests syncing is in-progress */
+
+ XIOErrorExitHandler exit_handler;
+ void *exit_handler_data;
};
#define XAllocIDs(dpy,ids,n) (*(dpy)->idlist_alloc)(dpy,ids,n)
@@ -929,7 +932,7 @@ extern int _XError(
);
extern int _XIOError(
Display* /* dpy */
-) _X_NORETURN;
+);
extern int (*_XIOErrorFunction)(
Display* /* dpy */
);
@@ -1385,6 +1388,10 @@ extern int _XDefaultError(
extern int _XDefaultIOError(
Display *dpy);
+extern void _XDefaultIOErrorExit(
+ Display *dpy,
+ void *user_data);
+
extern void _XSetClipRectangles (
Display *dpy,
GC gc,
diff --git a/man/XSetErrorHandler.man b/man/XSetErrorHandler.man
index 6ab5ae46..2f30420f 100644
--- a/man/XSetErrorHandler.man
+++ b/man/XSetErrorHandler.man
@@ -47,7 +47,7 @@
.ds xC Inter-Client Communication Conventions Manual
.TH XSetErrorHandler __libmansuffix__ __xorgversion__ "XLIB FUNCTIONS"
.SH NAME
-XSetErrorHandler, XGetErrorText, XDisplayName, XSetIOErrorHandler, XGetErrorDatabaseText \- default error handlers
+XSetErrorHandler, XGetErrorText, XDisplayName, XSetIOErrorHandler, XSetIOErrorExitHandler, XGetErrorDatabaseText \- default error handlers
.SH SYNTAX
.HP
int (*XSetErrorHandler\^(\^int (\^*\^\fIhandler\fP\^)\^(Display *, XErrorEvent
@@ -61,6 +61,10 @@ char *XDisplayName\^(\^_Xconst char *\fIstring\fP\^);
int (*XSetIOErrorHandler\^(\^int (\^*\^\fIhandler\fP\^)(Display
*)\^)\^)\^(\^);
.HP
+void (*XSetIOErrorExitHandler\^(Display
+*\fIdisplay\fP\^, void (\^*\^\fIhandler\fP\^)(Display *, void
+*)\^, void *\fIuser_data\fP)\^)\^(\^);
+.HP
int XGetErrorDatabaseText\^(\^Display *\fIdisplay\fP\^, _Xconst char *\fIname\fP, _Xconst char
*\fImessage\fP\^, _Xconst char *\fIdefault_string\fP\^, char *\fIbuffer_return\fP\^,
int \fIlength\fP\^);
@@ -136,9 +140,11 @@ sets the fatal I/O error handler.
Xlib calls the program's supplied error handler if any sort of system call
error occurs (for example, the connection to the server was lost).
This is assumed to be a fatal condition,
-and the called routine should not return.
+and the called routine should normally not return.
If the I/O error handler does return,
-the client process exits.
+the client process exits by default, this behavior may be altered with the
+.BR XSetIOErrorExitHandler
+function.
.LP
Note that the previous error handler is returned.
.LP
diff --git a/src/ErrHndlr.c b/src/ErrHndlr.c
index 167a68b1..0664ea93 100644
--- a/src/ErrHndlr.c
+++ b/src/ErrHndlr.c
@@ -84,3 +84,28 @@ XSetIOErrorHandler(XIOErrorHandler handler)
return (XIOErrorHandler) oldhandler;
}
+
+/*
+ * XSetIOErrorExitHandler - This procedure sets the X fatal I/O error
+ * exit function to be the specified routine. If NULL is passed in
+ * the original error exit function is restored. The default routine
+ * calls exit(3).
+ */
+void
+XSetIOErrorExitHandler(
+ Display *dpy,
+ XIOErrorExitHandler handler,
+ void *user_data)
+{
+ LockDisplay(dpy);
+
+ if (handler != NULL) {
+ dpy->exit_handler = handler;
+ dpy->exit_handler_data = user_data;
+ }
+ else {
+ dpy->exit_handler = _XDefaultIOErrorExit;
+ dpy->exit_handler_data = NULL;
+ }
+ UnlockDisplay(dpy);
+}
diff --git a/src/OpenDis.c b/src/OpenDis.c
index 59ffacca..b3cd8d99 100644
--- a/src/OpenDis.c
+++ b/src/OpenDis.c
@@ -188,6 +188,7 @@ XOpenDisplay (
dpy->flushes = NULL;
dpy->xcmisc_opcode = 0;
dpy->xkb_info = NULL;
+ dpy->exit_handler_data = NULL;
/*
* Setup other information in this display structure.
@@ -202,6 +203,7 @@ XOpenDisplay (
dpy->default_screen = iscreen; /* Value returned by ConnectDisplay */
dpy->last_req = (char *)&_dummy_request;
dpy->req_seq_syncing = False;
+ dpy->exit_handler = _XDefaultIOErrorExit;
/* Initialize the display lock */
if (InitDisplayLock(dpy) != 0) {
diff --git a/src/XlibInt.c b/src/XlibInt.c
index 69e22a9d..a316dba3 100644
--- a/src/XlibInt.c
+++ b/src/XlibInt.c
@@ -1273,6 +1273,14 @@ SocketBytesReadable(Display *dpy)
return bytes;
}
+_X_NORETURN void _XDefaultIOErrorExit(
+ Display *dpy,
+ void *user_data)
+{
+ exit(1);
+ /*NOTREACHED*/
+}
+
/*
* _XDefaultIOError - Default fatal system error reporting routine. Called
* when an X internal system error is encountered.
@@ -1509,6 +1517,9 @@ int
_XIOError (
Display *dpy)
{
+ XIOErrorExitHandler exit_handler;
+ void *exit_handler_data;
+
dpy->flags |= XlibDisplayIOError;
#ifdef WIN32
errno = WSAGetLastError();
@@ -1522,14 +1533,17 @@ _XIOError (
if (dpy->lock)
(*dpy->lock->user_lock_display)(dpy);
#endif
+ exit_handler = dpy->exit_handler;
+ exit_handler_data = dpy->exit_handler_data;
UnlockDisplay(dpy);
if (_XIOErrorFunction != NULL)
(*_XIOErrorFunction)(dpy);
else
_XDefaultIOError(dpy);
- exit (1);
- /*NOTREACHED*/
+
+ exit_handler(dpy, exit_handler_data);
+ return 1;
}