Subject: bug#16093: 24.3.50; Crash of emacs --daemon on killing X server

From: Dmitry Antipov <[email-masked]>
Date: Mon, 09 Dec 2013 21:57:59 +0400

On 12/09/2013 07:58 PM, Nix wrote:
>
> Start emacs --daemon (using the lucid toolkit), under X. Shut X down.
> Emacs crashes shortly afterwards.
>
>
> The lack of symbol table info is concerning (obviously my gdb has
> forgotten how to look up separated debug info *yet again*), but I don't
> think that important, since the death site is after a (garbage-collect)
> thus not in Lisp-land anyway. Obviously no xbacktrace is possible: the
> process is dead.
>
> It is fairly clear that we should not be calling xftfont_close() if the
> X server is not there! Why has this started happening?

Hm... IIUC there is no convenient way to check whether X display connection
is alive. But we can do some tricks, for example, try to select() or poll()
ConnectionNumber() - if there is no EBADF, X server is hopefully present...

Dmitry

=== modified file 'src/xfns.c'
--- src/xfns.c	2013-12-03 17:22:05 +0000
+++ src/xfns.c	2013-12-09 17:50:35 +0000
@@ -136,6 +136,20 @@
 
 static struct x_display_info *x_display_info_for_name (Lisp_Object);
 
+bool
+x_display_valid (Display *d)
+{
+  fd_set fdset;
+  struct timespec timeout;
+  int fd = ConnectionNumber (d); 
+
+  FD_ZERO (&fdset);
+  FD_SET (fd, &fdset);
+  timeout.tv_sec = 0;
+  timeout.tv_nsec = 1000;
+  return pselect (fd + 1, &fdset, NULL, NULL, &timeout, NULL) != -1;
+}
+
 /* Let the user specify an X display with a Lisp object.
    OBJECT may be nil, a frame or a terminal object.
    nil stands for the selected frame--or, if that is not an X frame,

=== modified file 'src/xfont.c'
--- src/xfont.c	2013-11-04 06:09:03 +0000
+++ src/xfont.c	2013-12-09 17:47:41 +0000
@@ -897,7 +897,8 @@
   if (xfi->xfont)
     {
       block_input ();
-      XFreeFont (xfi->display, xfi->xfont);
+      if (x_display_valid (xfi->display))
+	XFreeFont (xfi->display, xfi->xfont);
       unblock_input ();
       xfi->xfont = NULL;
     }

=== modified file 'src/xftfont.c'
--- src/xftfont.c	2013-10-27 05:30:34 +0000
+++ src/xftfont.c	2013-12-09 17:48:47 +0000
@@ -495,7 +495,8 @@
     {
       block_input ();
       XftUnlockFace (xftfont_info->xftfont);
-      XftFontClose (xftfont_info->display, xftfont_info->xftfont);
+      if (x_display_valid (xftfont_info->display))
+	XftFontClose (xftfont_info->display, xftfont_info->xftfont);
       unblock_input ();
       xftfont_info->xftfont = NULL;
     }

=== modified file 'src/xterm.h'
--- src/xterm.h	2013-12-07 23:04:10 +0000
+++ src/xterm.h	2013-12-09 17:46:16 +0000
@@ -989,6 +989,7 @@
 /* Defined in xfns.c */
 
 extern Lisp_Object x_get_focus_frame (struct frame *);
+extern bool x_display_valid (Display *);
 
 #ifdef USE_GTK
 extern int xg_set_icon (struct frame *, Lisp_Object);