mirror of
https://github.com/mirror/libX11.git
synced 2026-05-28 01:44:57 +08:00
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:
@@ -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 */,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user