]> git.eshelyaron.com Git - emacs.git/commitdiff
Load desktop without prompting if process is dead
authorStefan Kangas <stefankangas@gmail.com>
Thu, 24 Mar 2022 08:23:31 +0000 (09:23 +0100)
committerLars Ingebrigtsen <larsi@gnus.org>
Thu, 24 Mar 2022 08:23:31 +0000 (09:23 +0100)
* doc/emacs/misc.texi (Saving Emacs Sessions): Document the new
'check' value.
* etc/NEWS: Announce the change (bug#1474).
* lisp/desktop.el (desktop-load-locked-desktop): Add new value 'check'
to load desktop file without prompting if locking Emacs process does
not exist on the local machine.  (Bug#1474)
(desktop-read): Extract function from here...
(desktop--load-locked-desktop-p): ...to here.  New function handles
the semantics of 'desktop-load-locked-desktop', including above new
value 'check'.
(desktop--emacs-pid-running-p): New function.

* test/lisp/desktop-tests.el: New file with tests for the above.

doc/emacs/misc.texi
etc/NEWS
lisp/desktop.el
test/lisp/desktop-tests.el [new file with mode: 0644]

index 4710c05b620b244ffc0118c3ac9e956e3b3c6244..a0d79711f10de9b1bf9d7c10554e5bc15956f5c7 100644 (file)
@@ -2770,7 +2770,12 @@ will by default ask you whether to use the locked desktop file.  You
 can avoid the question by customizing the variable
 @code{desktop-load-locked-desktop} to either @code{nil}, which means
 never load the desktop in this case, or @code{t}, which means load the
-desktop without asking.
+desktop without asking.  Finally, the @code{check-pid} value means to
+load the file if the Emacs process that has locked the desktop is not
+running on the local machine.  This should not be used in
+circumstances where the locking Emacs might still be running on
+another machine.  This could be the case in multi-user environments
+where your home directory is mounted remotely using NFS or similar.
 
 @cindex desktop restore in daemon mode
   When Emacs starts in daemon mode, it cannot ask you any questions,
index ad0f7f1c055473b64522a104e9b9cd21a445248c..5ca1df45425ac8b7f1838d9fbaa33c90bbf2054c 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -83,6 +83,15 @@ input of sequences such as 'C-;' and 'C-S-u'.
 Instead, they're fetched as needed from the corresponding ".elc" file,
 as was already the case for all the non-preloaded files.
 
+** Emacs Sessions (Desktop)
+
++++
+*** New option to load if locking Emacs not running locally.
+The option 'desktop-load-locked-desktop' can now be set to value
+'check-pid', which means to load the desktop only if the locking Emacs
+process is not running on the local machine.  See the "(emacs) Saving
+Emacs Sessions" node in the Emacs manual for details.
+
 \f
 * Startup Changes in Emacs 29.1
 
index e7a368e21f52c63ca6b9f7f417e8c4bc7b21d36e..773f0f050f996a88af46c23de04770308ef8188a 100644 (file)
@@ -230,16 +230,26 @@ Zero or nil means disable auto-saving due to idleness."
 (defcustom desktop-load-locked-desktop 'ask
   "Specifies whether the desktop should be loaded if locked.
 Possible values are:
-   t    -- load anyway.
-   nil  -- don't load.
-   ask  -- ask the user.
-If the value is nil, or `ask' and the user chooses not to load the desktop,
-the normal hook `desktop-not-loaded-hook' is run."
+   t          -- load anyway.
+   nil        -- don't load.
+   ask        -- ask the user.
+   check-pid  -- load if locking Emacs process is missing locally.
+
+If the value is nil, or `ask' and the user chooses not to load
+the desktop, the normal hook `desktop-not-loaded-hook' is run.
+
+If the value is `check-pid', load the desktop if the Emacs
+process that has locked it is not running on the local machine.
+This should not be used in circumstances where the locking Emacs
+might still be running on another machine.  That could be the
+case if you have remotely mounted (NFS) paths in
+`desktop-dirname'."
   :type
   '(choice
     (const :tag "Load anyway" t)
     (const :tag "Don't load" nil)
-    (const :tag "Ask the user" ask))
+    (const :tag "Ask the user" ask)
+    (const :tag "Load if no local process" check-pid))
   :group 'desktop
   :version "22.2")
 
@@ -662,6 +672,28 @@ DIRNAME omitted or nil means use `desktop-dirname'."
             (integerp owner)))
         owner)))
 
+(defun desktop--emacs-pid-running-p (pid)
+  "Return t if an Emacs process with PID exists."
+  (when-let ((attr (process-attributes pid)))
+    (equal (alist-get 'comm attr)
+           (file-name-nondirectory (car command-line-args)))))
+
+(defun desktop--load-locked-desktop-p (owner)
+  "Return t if a locked desktop should be loaded.
+OWNER is the pid in the lock file.
+The return value of this function depends on the value of
+`desktop-load-locked-desktop'."
+  (pcase desktop-load-locked-desktop
+    ('ask
+     (unless (daemonp)
+       (y-or-n-p (format "Warning: desktop file appears to be in use by PID %s.\n\
+Using it may cause conflicts.  Use it anyway? " owner))))
+    ('check-pid
+     (or (eq (emacs-pid) owner)
+         (not (desktop--emacs-pid-running-p owner))))
+    ('nil nil)
+    (_ t)))
+
 (defun desktop-claim-lock (&optional dirname)
   "Record this Emacs process as the owner of the desktop file in DIRNAME.
 DIRNAME omitted or nil means use `desktop-dirname'."
@@ -1263,11 +1295,7 @@ It returns t if a desktop file was loaded, nil otherwise.
              (desktop-save nil)
              (desktop-autosave-was-enabled))
          (if (and owner
-                  (memq desktop-load-locked-desktop '(nil ask))
-                  (or (null desktop-load-locked-desktop)
-                      (daemonp)
-                      (not (y-or-n-p (format "Warning: desktop file appears to be in use by PID %s.\n\
-Using it may cause conflicts.  Use it anyway? " owner)))))
+                   (not (desktop--load-locked-desktop-p owner)))
              (let ((default-directory desktop-dirname))
                (setq desktop-dirname nil)
                (run-hooks 'desktop-not-loaded-hook)
diff --git a/test/lisp/desktop-tests.el b/test/lisp/desktop-tests.el
new file mode 100644 (file)
index 0000000..d52fe39
--- /dev/null
@@ -0,0 +1,50 @@
+;;; desktop-tests.el --- Tests for desktop.el  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2020 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'ert)
+(require 'desktop)
+
+(ert-deftest desktop-tests--emacs-pid-running-p ()
+  (should (desktop--emacs-pid-running-p (emacs-pid)))
+  (should-not (desktop--emacs-pid-running-p 1)))
+
+(ert-deftest desktop-tests--load-locked-desktop-p ()
+  (let ((desktop-load-locked-desktop t))
+    (should (desktop--load-locked-desktop-p (emacs-pid)))))
+
+(ert-deftest desktop-tests--load-locked-desktop-p-nil ()
+  (let ((desktop-load-locked-desktop nil))
+    (should-not (desktop--load-locked-desktop-p (emacs-pid)))))
+
+(ert-deftest desktop-tests--load-locked-desktop-p-ask ()
+ (let ((desktop-load-locked-desktop 'ask))
+   (cl-letf (((symbol-function 'y-or-n-p) (lambda (&rest _) t)))
+     (should (desktop--load-locked-desktop-p (emacs-pid))))
+   (cl-letf (((symbol-function 'y-or-n-p) (lambda (&rest _) nil)))
+     (should-not (desktop--load-locked-desktop-p (emacs-pid))))))
+
+(ert-deftest desktop-tests--load-locked-desktop-p-check ()
+  (let ((desktop-load-locked-desktop 'check-pid))
+    (desktop--load-locked-desktop-p (emacs-pid))))
+
+(provide 'desktop-tests)