Like many users of XFree86, I can make my X server crash by evaluating this
Lisp code:
(read-from-minibuffer "\t")
I also use XEmacs as a server, connecting to it with gnuclient in my X init
scripts. I run this in /etc/rc.local on startup:
( . /home/aidan/.shrc && /usr/pkg/bin/sudo -u aidan /usr/pkg/bin/screen -d
-m /usr/local/bin/xemacs )
This should make it possible to resume my XEmacs session after such an X
server crash, since it provides a TTY frame, and since the
x_IO_error_handler only aborts if there is no other existing XEmacs frame.
However, the x_IO_error_handler doesn’t immediately delete the X device, it
queues an event to do so, and then throws to top level. If this happens
during read-from-minibuffer, read-from-minibuffer tries to restore the old
window and frame configuration, before the “delete the X device” event is
processed. This calls X11 code, and calling X11 code with a no-longer-valid
Display argument in this case hangs. The patch checks whether the device is
being deleted (and whether the frame is live, for good measure) and avoids
calling X code if so.
Tangentally, looking at the X11 code, there are a few places that currently
call ABORT() that should be doing roughly what x_IO_error_handler does
instead. Does anyone in principle object to my reworking them?
src/ChangeLog addition:
2006-05-07 Aidan Kehoe <kehoea(a)parhasard.net>
* frame-x.c (x_set_frame_properties):
Check that the frame is live and that the device is not being
deleted before attempting anything. Avoids calling X code if
x_IO_error_handler has seen a broken pipe.
XEmacs Trunk source patch:
Diff command: cvs -q diff -u
Files affected: src/frame-x.c
Index: src/frame-x.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/frame-x.c,v
retrieving revision 1.73
diff -u -u -r1.73 frame-x.c
--- src/frame-x.c 2006/05/06 17:56:00 1.73
+++ src/frame-x.c 2006/05/07 11:42:24
@@ -745,7 +745,14 @@
Bool y_position_specified_p = False;
Bool internal_border_width_specified = False;
Lisp_Object tail;
- Widget w = FRAME_X_TEXT_WIDGET (f);
+ Widget w;
+
+ /* We can be called after the X IO error handler has seen a broken pipe on
+ the relevant display. Don't do anything in that case. */
+ if (!FRAME_LIVE_P (f) || DEVICE_X_BEING_DELETED (XDEVICE (FRAME_DEVICE (f))))
+ return;
+
+ w = FRAME_X_TEXT_WIDGET (f);
for (tail = plist; !NILP (tail); tail = Fcdr (Fcdr (tail)))
{
--
Aidan Kehoe,
http://www.parhasard.net/