In server-unselect-display make sure that buffer is live before killing it
[bpt/emacs.git] / lisp / server.el
index c91f10b..61787db 100644 (file)
@@ -1,6 +1,6 @@
 ;;; server.el --- Lisp code for GNU Emacs running as server process -*- lexical-binding: t -*-
 
-;; Copyright (C) 1986-1987, 1992, 1994-2011  Free Software Foundation, Inc.
+;; Copyright (C) 1986-1987, 1992, 1994-2012  Free Software Foundation, Inc.
 
 ;; Author: William Sommerfeld <wesommer@athena.mit.edu>
 ;; Maintainer: FSF
@@ -112,7 +112,10 @@ If set, the server accepts remote connections; otherwise it is local."
 (put 'server-host 'risky-local-variable t)
 
 (defcustom server-port nil
-  "The port number that the server process should listen on."
+  "The port number that the server process should listen on.
+This variable only takes effect when the Emacs server is using
+TCP instead of local sockets.  A nil value means to use a random
+port number."
   :group 'server
   :type '(choice
           (string :tag "Port number")
@@ -123,6 +126,8 @@ If set, the server accepts remote connections; otherwise it is local."
 
 (defcustom server-auth-dir (locate-user-emacs-file "server/")
   "Directory for server authentication files.
+We only use this if `server-use-tcp' is non-nil.
+Otherwise we use `server-socket-dir'.
 
 NOTE: On FAT32 filesystems, directories are not secure;
 files can be read and modified by any user or process.
@@ -304,11 +309,13 @@ Updates `server-clients'."
 
       (setq server-clients (delq proc server-clients))
 
-      ;; Delete the client's tty.
-      (let ((terminal (process-get proc 'terminal)))
-       ;; Only delete the terminal if it is non-nil.
-       (when (and terminal (eq (terminal-live-p terminal) t))
-         (delete-terminal terminal)))
+      ;; Delete the client's tty, except on Windows (both GUI and console),
+      ;; where there's only one terminal and does not make sense to delete it.
+      (unless (eq system-type 'windows-nt)
+       (let ((terminal (process-get proc 'terminal)))
+         ;; Only delete the terminal if it is non-nil.
+         (when (and terminal (eq (terminal-live-p terminal) t))
+           (delete-terminal terminal))))
 
       ;; Delete the client's process.
       (if (eq (process-status proc) 'open)
@@ -392,16 +399,19 @@ If CLIENT is non-nil, add a description of it to the logged message."
     ;; visible.  If not (which can happen if the user's customizations call
     ;; pop-to-buffer etc.), delete it to avoid preserving the connection after
     ;; the last real frame is deleted.
-    (if (and (eq (frame-first-window frame)
-                 (next-window (frame-first-window frame) 'nomini))
-             (eq (window-buffer (frame-first-window frame))
-                 (frame-parameter frame 'server-dummy-buffer)))
-        ;; The temp frame still only shows one buffer, and that is the
-        ;; internal temp buffer.
-        (delete-frame frame)
-      (set-frame-parameter frame 'visibility t))
-    (kill-buffer (frame-parameter frame 'server-dummy-buffer))
-    (set-frame-parameter frame 'server-dummy-buffer nil)))
+
+    ;; Rewritten to avoid inadvertently killing the current buffer after
+    ;; `delete-frame' removed FRAME (Bug#10729).
+    (let ((buffer (frame-parameter frame 'server-dummy-buffer)))
+      (when (buffer-live-p buffer)
+       (if (and (one-window-p 'nomini frame)
+                (eq (window-buffer (frame-first-window frame)) buffer))
+           ;; The temp frame still only shows one buffer, and that is the
+           ;; internal temp buffer.
+           (delete-frame frame)
+         (set-frame-parameter frame 'visibility t)
+         (set-frame-parameter frame 'server-dummy-buffer nil))
+       (kill-buffer buffer)))))
 
 (defun server-handle-delete-frame (frame)
   "Delete the client connection when the emacsclient frame is deleted.
@@ -666,9 +676,13 @@ Return values:
 ;;;###autoload
 (define-minor-mode server-mode
   "Toggle Server mode.
-With ARG, turn Server mode on if ARG is positive, off otherwise.
+With a prefix argument ARG, enable Server mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+Server mode if ARG is omitted or nil.
+
 Server mode runs a process that accepts commands from the
-`emacsclient' program.  See `server-start' and Info node `Emacs server'."
+`emacsclient' program.  See Info node `Emacs server' and
+`server-start' for details."
   :global t
   :group 'server
   :version "22.1"
@@ -678,7 +692,14 @@ Server mode runs a process that accepts commands from the
 \f
 (defun server-eval-and-print (expr proc)
   "Eval EXPR and send the result back to client PROC."
-  (let ((v (eval (car (read-from-string expr)))))
+  ;; While we're running asynchronously (from a process filter), it is likely
+  ;; that the emacsclient command was run in response to a user
+  ;; action, so the user probably knows that Emacs is processing this
+  ;; emacsclient request, so if we get a C-g it's likely that the user
+  ;; intended it to interrupt us rather than interrupt whatever Emacs
+  ;; was doing before it started handling the process filter.
+  ;; Hence `with-local-quit' (bug#6585).
+  (let ((v (with-local-quit (eval (car (read-from-string expr))))))
     (when proc
       (with-temp-buffer
         (let ((standard-output (current-buffer)))
@@ -1021,7 +1042,11 @@ The following commands are accepted by the client:
                  (setq tty-name (pop args-left)
                        tty-type (pop args-left)
                        dontkill (or dontkill
-                                    (not use-current-frame))))
+                                    (not use-current-frame)))
+                 ;; On Windows, emacsclient always asks for a tty frame.
+                 ;; If running a GUI server, force the frame type to GUI.
+                 (when (eq window-system 'w32)
+                   (push "-window-system" args-left)))
 
                 ;; -position LINE[:COLUMN]:  Set point to the given
                 ;;  position in the next file.
@@ -1505,7 +1530,14 @@ only these files will be asked to be saved."
   nil)
 
 (defun server-eval-at (server form)
-  "Eval FORM on Emacs Server SERVER."
+  "Contact the Emacs server named SERVER and evaluate FORM there.
+Returns the result of the evaluation, or signals an error if it
+cannot contact the specified server.  For example:
+  \(server-eval-at \"server\" '(emacs-pid))
+returns the process ID of the Emacs instance running \"server\".
+This function requires the use of TCP sockets. "
+  (or server-use-tcp
+      (error "This function requires TCP sockets"))
   (let ((auth-file (expand-file-name server server-auth-dir))
        (coding-system-for-read 'binary)
        (coding-system-for-write 'binary)