1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-30 04:10:54 -08:00

Load desktop without prompting if process is dead

* 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.
This commit is contained in:
Stefan Kangas 2022-03-24 09:23:31 +01:00 committed by Lars Ingebrigtsen
parent 72ab6c4f14
commit b4f504a0ea
4 changed files with 104 additions and 12 deletions

View 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,

View file

@ -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.
* Startup Changes in Emacs 29.1

View 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)

View file

@ -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)