Subject: Re: bug#17975: 24.3.92; assertion failure deleting frames with varying names for the same display (and, using multiple X11 connections in that case too)

From: Dmitry Antipov <[email-masked]>
Date: Wed, 09 Jul 2014 09:37:49 +0400

On 07/08/2014 11:59 PM, Ken Raeburn wrote:

> This is a simplified version of a crash I got using emacsclient, daemon
> mode, and desktop-save-mode. My saved desktop configuration somehow has
> frames with different names for the same local display, perhaps because
> window manager buttons I use to invoke emacsclient cause ":0.0" to be
> used, and my xterm shells have DISPLAY set to ":0".
>
> Emacs is compiled with "--enable-checking --with-x-toolkit=lucid".
>
> Recipe:
>   1. emacs -Q --daemon
>   2. DISPLAY=:0 emacsclient -c -n
>   3. DISPLAY=:0.0 emacsclient -c -n
>   4. Use	a window-manager button	to delete the first Emacs window.
>   5. Emacs crashes with an assertion failure.

Reproduced. The whole thing looks like a mystery (perhaps Xlib makes a
difference between :0 and :0.0 somewhere in its innards), but this
workaround works for me. Can you please try it too?

Dmitry

=== modified file 'lib-src/emacsclient.c'
--- lib-src/emacsclient.c	2014-06-17 16:09:19 +0000
+++ lib-src/emacsclient.c	2014-07-09 05:30:11 +0000
@@ -82,6 +82,8 @@
 #include <signal.h>
 #include <errno.h>
 
+#include <intprops.h>
+
 #ifndef VERSION
 #define VERSION "unspecified"
 #endif
@@ -1517,6 +1519,31 @@
 #endif /* WINDOWSNT */
 }
 
+/* Return the canonical HOST:SEQUENCE.SCREEN name of DISPLAY.
+   For some weird reason, this is important for XIM (Bug#17975).  */
+
+static char *
+x_canonical_display (char *display)
+{
+  char host[256]; /* Max. FQDN length is 255.  */
+  int sequence, screen;
+  
+  if (sscanf (display, "%s:%d.%d", host, &sequence, &screen) == 3)
+    /* canonical */ ;
+  else if (sscanf (display, "%d:%d", &sequence, &screen) == 2
+	   || sscanf (display, ":%d:%d", &sequence, &screen) == 2)
+    {
+      display = xmalloc (4 + INT_BUFSIZE_BOUND (int) * 2 + 3);
+      sprintf (display, "unix:%d.%d", sequence, screen);
+    }
+  else if (sscanf (display, ":%d", &sequence) == 1)
+    {
+      display = xmalloc (4 + INT_BUFSIZE_BOUND (int) + 4);
+      sprintf (display, "unix:%d.0", sequence);
+    }
+  return display;
+}
+
 int
 main (int argc, char **argv)
 {
@@ -1585,6 +1612,9 @@
   w32_give_focus ();
 #endif /* HAVE_NTGUI */
 
+  if (display)
+    display = x_canonical_display ((char *) display);
+
   /* Send over our environment and current directory. */
   if (!current_frame)
     {