diff --git a/lisp/server.el b/lisp/server.el index b65053267a6..7d8b8d37fad 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -1046,6 +1046,8 @@ server-execute-continuation (process-put proc 'continuation nil) (if continuation (ignore-errors (funcall continuation))))) +(defvar server--pending-filter-calls t) + (cl-defun server-process-filter (proc string) "Process a request from the server to edit some files. PROC is the server process. STRING consists of a sequence of @@ -1145,6 +1147,18 @@ server-process-filter `-suspend' Suspend this terminal, i.e., stop the client process. Sent when the user presses \\[suspend-frame]." + (if (listp server--pending-filter-calls) + ;; We're already running another instance of this process filter. + ;; Let's make sure we don't run them in a nested fashion. + (push (cons proc string) server--pending-filter-calls) + (let ((server--pending-filter-calls nil)) + (push (cons proc string) server--pending-filter-calls) + (while server--pending-filter-calls + (dolist (pending-call (prog1 (nreverse server--pending-filter-calls) + (setq server--pending-filter-calls nil))) + (server--process-filter (car pending-call) (cdr pending-call))))))) + +(cl-defun server--process-filter (proc string) (server-log (concat "Received " string) proc) ;; First things first: let's check the authentication (unless (process-get proc :authenticated) @@ -1159,6 +1173,9 @@ server-process-filter ;; it, in case the error written by emacsclient to stderr is not ;; visible for some reason. (message "Authentication failed") + ;; FIXME: Ideally we should not need `sit-for' here and instead use + ;; some `message-timed' call which makes sure the message is visible + ;; without forcing us to wait here. (sit-for 2) (server-send-string proc (concat "-error " (server-quote-arg "Authentication failed"))) @@ -1169,10 +1186,9 @@ server-process-filter (delete-terminal terminal)))) ;; Before calling `delete-process', give emacsclient time to ;; receive the error string and shut down on its own. - (sit-for 1) - (delete-process proc) + (run-with-timer 1 nil #'delete-process proc) ;; We return immediately. - (cl-return-from server-process-filter))) + (cl-return-from server--process-filter))) (let ((prev (process-get proc 'previous-string))) (when prev (setq string (concat prev string)) @@ -1508,6 +1524,9 @@ server-return-error ;; it, in case the error written by emacsclient to stderr is not ;; visible for some reason. (message (error-message-string err)) + ;; FIXME: Ideally we should not need `sit-for' here and instead use + ;; some `message-timed' call which makes sure the message is visible + ;; without forcing us to wait here. (sit-for 2) (server-send-string proc (concat "-error " (server-quote-arg @@ -1520,7 +1539,7 @@ server-return-error (delete-terminal terminal)))) ;; Before calling `delete-process', give emacsclient time to ;; receive the error string and shut down on its own. - (sit-for 5) + (run-with-timer 5 nil #'delete-process proc) (delete-process proc))) (defun server-goto-line-column (line-col)