Subject: [PATCH] project.el: avoid asking user about project-list-file lock

From: Spencer Baugh <[email-masked]>
Date: Tue, 07 Nov 2023 16:28:04 -0500

Tags: patch

This fixes a periodic issue that happens with multiple Emacs instances
and project.el.

Maybe this isn't the right way to change the behavior of
ask-user-about-lock though; possibly we should add some new defcustom to
customize it.  Happy to do that if that's preferred.

In GNU Emacs 29.1.50 (build 15, x86_64-pc-linux-gnu, X toolkit, cairo
 version 1.15.12, Xaw scroll bars) of 2023-10-25 built on
 igm-qws-u22796a
Repository revision: 5cbca757f620c7b4ca31776711a247b8f266c36e
Repository branch: emacs-29
Windowing system distributor 'The X.Org Foundation', version 11.0.12011000
System Description: Rocky Linux 8.8 (Green Obsidian)

Configured using:
 'configure --config-cache --with-x-toolkit=lucid
 --with-gif=ifavailable'

>From ec6caaf9fcb913847278f7183e46d3026c6986fb Mon Sep 17 00:00:00 2001
From: Spencer Baugh <[email-masked]>
Date: Tue, 7 Nov 2023 16:24:26 -0500
Subject: [PATCH] project.el: avoid asking user about project-list-file lock

There are several features which will cause Emacs to frequently call
project-current, and therefore call project-remember-project, and
therefore sometimes call project--write-project-list whenever a new
project is seen.

- project-uniquify-dirname-transform will call this for each new
  buffer

- project-mode-line will call this on mode-line update

- My own private project-watch will call this based on file-notify
  events.

If a user has multiple Emacs instances open using one or more of these
features, it's fairly easy for both of the Emacs instances to see a
new project at the same time.  In that case, they'll both call
project--write-project-list at the same time, which will clash and run
ask-user-about-lock.  This will happen frequently if the user is often
looking at new projects.

There's no correct answer the user can give to ask-user-about-lock:
either way, one of the Emacs instances will have its project-list-file
update lost.  So let's not even bother prompting the user: just do
nothing if project-list-file is currently locked.

In the long run, the update doesn't actually get lost, because the
Emacs instance will probably make the same project-list-file update
again a few seconds later due to a later call to project-current.  So
this doesn't lose anything.

* lisp/progmodes/project.el (project--write-project-list): No-op if
the file is locked.
---
 lisp/progmodes/project.el | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 43c78f8b16b..78aaa75de5f 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1719,7 +1719,13 @@ project--write-project-list
                                 (expand-file-name name)))))
                     project--list)
             (current-buffer)))
-      (write-region nil nil filename nil 'silent))))
+      ;; If project-list-file is locked by some other Emacs, fail to
+      ;; write rather than prompting the user.
+      (ignore-error file-locked
+        (cl-letf (((symbol-function 'ask-user-about-lock)
+                   (lambda (file opponent)
+                     (signal 'file-locked (list file opponent)))))
+          (write-region nil nil filename nil 'silent))))))
 
 ;;;###autoload
 (defun project-remember-project (pr &optional no-write)
-- 
2.39.3