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>
This commit is contained in:
Carlos Garnacho
2019-06-14 17:55:14 +02:00
parent 4cb758019e
commit 9f9c536581
6 changed files with 70 additions and 6 deletions

View File

@@ -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 */,

View File

@@ -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,

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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;
}