Subject: bug#17510: 24.3.91; Problem with `emacs --daemon' in cygw32 build

From: Ken Brown <[email-masked]>
Date: Sat, 17 May 2014 19:39:33 -0400

On 5/16/2014 4:06 PM, Ken Brown wrote:
> On 5/16/2014 1:50 PM, Ken Brown wrote:
>> This bug was reported in the Cygwin mailing list:
>>
>>    https://cygwin.com/ml/cygwin/2014-05/msg00303.html
>>
>> In a Cygwin terminal, do the following, where "emacs" denotes the cygw32
>> build of emacs (--with-w32).
>>
>> 1. $ emacs --daemon -Q
>> 2. $ emacsclient -c
>> 3. `C-x 5 0' in the client window to exit the frame.
>> 4. Repeat steps 2 and 3.
>> 5. Attempt to carry out steps 2 and 3 a third time.  The message
>> "Waiting for Emacs..." appears in the terminal, but no new frame opens.
>>
>> This problem is specific to the cygw32 build; it does not happen with
>> the X11 build of emacs on Cygwin.  It also doesn't happen if the server
>> is started via `M-x server-start' in an existing emacs.
>
> And it doesn't happen in emacs-24.3.  As soon as I have a chance, I'll
> do a bisection to see when it started.

Here's the culprit:

revno: 114710
committer: Dmitry Antipov <[email-masked]>
branch nick: trunk
timestamp: Fri 2013-10-18 16:57:44 +0400
message:
   Remove port-specific display name lists to avoid extra
   complexity and data duplication with display info lists.
[...]
   * w32term.h (w32_display_name_list): Remove declaration.
   * w32term.c (w32_display_name_list): Remove.
   (w32_initialize_display_info, x_delete_display, syms_of_w32term):
   Adjust users.
   * w32fns.c (x_display_info_for_name, Fx_display_list):
   Likewise.  Use x_display_list where appropriate.
[...]

The attached patch applied to the emacs-24 branch reverts these changes 
and fixes the problem.  This is presumably no the "right" fix.  Note, 
however, that Dimity's commit introduced a "FIXME" into x_delete_display 
in w32term.c.  Maybe that's the issue.

Ken
=== modified file 'src/w32fns.c'
--- src/w32fns.c	2014-05-06 16:00:30 +0000
+++ src/w32fns.c	2014-05-17 22:15:56 +0000
@@ -5184,13 +5184,20 @@
 struct w32_display_info *
 x_display_info_for_name (Lisp_Object name)
 {
+  Lisp_Object names;
   struct w32_display_info *dpyinfo;
 
   CHECK_STRING (name);
 
-  for (dpyinfo = &one_w32_display_info; dpyinfo; dpyinfo = dpyinfo->next)
-    if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
-      return dpyinfo;
+  for (dpyinfo = &one_w32_display_info, names = w32_display_name_list;
+       dpyinfo && !NILP (w32_display_name_list);
+       dpyinfo = dpyinfo->next, names = XCDR (names))
+    {
+      Lisp_Object tem;
+      tem = Fstring_equal (XCAR (XCAR (names)), name);
+      if (!NILP (tem))
+	return dpyinfo;
+    }
 
   /* Use this general default value to start with.  */
   Vx_resource_name = Vinvocation_name;
@@ -5325,11 +5332,11 @@
        doc: /* Return the list of display names that Emacs has connections to.  */)
   (void)
 {
-  Lisp_Object result = Qnil;
-  struct w32_display_info *wdi;
+  Lisp_Object tail, result;
 
-  for (wdi = x_display_list; wdi; wdi = wdi->next)
-    result = Fcons (XCAR (wdi->name_list_element), result);
+  result = Qnil;
+  for (tail = w32_display_name_list; CONSP (tail); tail = XCDR (tail))
+    result = Fcons (XCAR (XCAR (tail)), result);
 
   return result;
 }

=== modified file 'src/w32term.c'
--- src/w32term.c	2014-04-16 14:00:39 +0000
+++ src/w32term.c	2014-05-17 22:15:56 +0000
@@ -100,6 +100,13 @@
 struct w32_display_info one_w32_display_info;
 struct w32_display_info *x_display_list;
 
+/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
+   one for each element of w32_display_list and in the same order.
+   NAME is the name of the frame.
+   FONT-LIST-CACHE records previous values returned by x-list-fonts.  */
+Lisp_Object w32_display_name_list;
+
+
 #if _WIN32_WINNT < 0x0500 && !defined(_W64)
 /* Pre Windows 2000, this was not available, but define it here so
    that Emacs compiled on such a platform will run on newer versions.
@@ -6161,7 +6168,11 @@
 
   memset (dpyinfo, 0, sizeof (*dpyinfo));
 
-  dpyinfo->name_list_element = Fcons (display_name, Qnil);
+  /* Put it on w32_display_name_list.  */
+  w32_display_name_list = Fcons (Fcons (display_name, Qnil),
+                                 w32_display_name_list);
+  dpyinfo->name_list_element = XCAR (w32_display_name_list);
+
   dpyinfo->w32_id_name = xmalloc (SCHARS (Vinvocation_name)
 				  + SCHARS (Vsystem_name) + 2);
   sprintf (dpyinfo->w32_id_name, "%s@%s",
@@ -6410,7 +6421,27 @@
 void
 x_delete_display (struct w32_display_info *dpyinfo)
 {
-  /* FIXME: the only display info apparently can't be deleted.  */
+  /* Discard this display from w32_display_name_list and w32_display_list.
+     We can't use Fdelq because that can quit.  */
+  if (! NILP (w32_display_name_list)
+      && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
+    w32_display_name_list = XCDR (w32_display_name_list);
+  else
+    {
+      Lisp_Object tail;
+
+      tail = w32_display_name_list;
+      while (CONSP (tail) && CONSP (XCDR (tail)))
+	{
+	  if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
+	    {
+	      XSETCDR (tail, XCDR (XCDR (tail)));
+	      break;
+	    }
+	  tail = XCDR (tail);
+	}
+    }
+
   /* free palette table */
   {
     struct w32_palette_entry * plist;
@@ -6547,6 +6578,9 @@
 void
 syms_of_w32term (void)
 {
+  staticpro (&w32_display_name_list);
+  w32_display_name_list = Qnil;
+
   DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
 
   DEFSYM (Qadded, "added");

=== modified file 'src/w32term.h'
--- src/w32term.h	2014-02-04 16:13:51 +0000
+++ src/w32term.h	2014-05-17 22:15:56 +0000
@@ -71,7 +71,8 @@
   /* The generic display parameters corresponding to this w32 display.  */
   struct terminal *terminal;
 
-  /* This is a cons cell of the form (NAME . FONT-LIST-CACHE).  */
+  /* This is a cons cell of the form (NAME . FONT-LIST-CACHE).
+     The same cons cell also appears in x_display_name_list.  */
   Lisp_Object name_list_element;
 
   /* Number of frames that are on this display.  */
@@ -200,6 +201,12 @@
 extern struct w32_display_info *x_display_list;
 extern struct w32_display_info one_w32_display_info;
 
+/* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
+   one for each element of w32_display_list and in the same order.
+   NAME is the name of the frame.
+   FONT-LIST-CACHE records previous values returned by x-list-fonts.  */
+extern Lisp_Object w32_display_name_list;
+
 extern struct frame *x_window_to_frame (struct w32_display_info *, HWND);
 
 struct w32_display_info *x_display_info_for_name (Lisp_Object);