Subject: Re: bug#11102: 24.0.94; C-x C-c from a client frame sometimes kills the whole Emacs process

From: Chong Yidong <[email-masked]>
Date: Sat, 14 Apr 2012 13:34:27 +0800

Chong Yidong <[email-masked]> writes:

> If on a client frame created by "emacsclient -c -n" the C-x C-c command
> kills Emacs, that is indeed a bug.  My guess would be that the `client'
> frame parameter is not getting correctly assigned to the newly-created
> frame on Windows, due to the extra juggling in the #ifdef WINDOWSNT code
> segment Juanma pointed out.

Took a quick look, and indeed the "set tty = 1 on Windows" hack does
seem to be at fault.  Here's my diagnosis:

  if (tty || !current_frame)
    {
      display = (const char *) ttyname (0);  /* Arg is ignored.  */
      current_frame = 0;
      tty = 1;
    }

  ...

  /* --no-wait implies --current-frame on ttys when there are file
     arguments or expressions given.  */
  if (nowait && tty && argc - optind > 0)
    current_frame = 1;

When tty = 1, if there are also -n and filename arguments, emacsclient
assumes that a current Emacs frame must be used.  This assumption is not
correct if the tty = 1 is because of the Window hack.  As a result, the
server calls `server-select-display', which ends up trying to create a
new frame on the display ttyname(0), contra the "Arg is ignored"
comment.  That new frame, if created, lacks the `client' frame parameter
for C-x C-c to work right.

Does the following patch DTRT?  This is an attempt at making a minimal
change, for Emacs 24.1.  For the trunk, I think it is worth trying to
untangle the logic properly, but that will needs Someone(tm) to work on
it who has access to a Windows box.

=== modified file 'lisp/server.el'
*** lisp/server.el	2012-04-04 17:13:00 +0000
--- lisp/server.el	2012-04-14 05:29:24 +0000
***************
*** 1136,1141 ****
--- 1136,1145 ----
  	    (setq frame
  		  (cond
  		   ((and use-current-frame
+ 			 ;; On Windows, we pass -tty as a hack, using
+ 			 ;; a bogus display name.
+ 			 (or (not (eq window-system 'w32))
+ 			     (equal display "CONOUT$"))
  			 (or (eq use-current-frame 'always)
  			     ;; We can't use the Emacs daemon's
  			     ;; terminal frame.