all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Johan Claesson <johanclaesson@bredband.net>
To: Lars Ingebrigtsen <larsi@gnus.org>
Cc: 13860@debbugs.gnu.org
Subject: bug#13860: 24.2; dir-locals-directory-cache unreliable in one rare case
Date: Sun, 18 Aug 2019 21:19:01 +0200	[thread overview]
Message-ID: <87y2zqs2my.fsf@bredband.net> (raw)
In-Reply-To: <8736i3ymrf.fsf@mouse.gnus.org> (Lars Ingebrigtsen's message of "Wed, 14 Aug 2019 23:18:44 -0700")




Hi Lars,

I can reproduce with emacs -Q on Emacs 27 (ee1c638cff).  I get the wrong
value about 1 time in 3 tries.

(I cannot reproduce without -Q.  In particular when magit-autorevert is
loaded that will "fix" the issue.  Probably by slowing things down.)

My original description is a bit incorrect/misleading.  The race
condition is not about if it occurs in the same second or not.  But it
is about when two file modification timestamps are equal.

What happens seem to be that sometimes the second time the
.dir-locals.el file is written (now with value foo = 2) the file will
get the same timestamp as it already have from the first write.  At this
point the dir-locals-class-alist cache is not updated (it still have foo
= 1).

The cache is supposed to be updated when reading the .dir-locals.el. 
But that is only done if .dir-locals.el modification timestamp is newer
than the timestamp in the cache.  Sometimes they are the same just because 
the clock have not ticked forward.

I think one way to remedy this would be to explicitly invalidate the
directory cache every time a .dir-local.el file is modified.  Something
like the following seem to do the trick:

diff --git a/lisp/files-x.el b/lisp/files-x.el
index b71e9204f3..6b04518fe4 100644
--- a/lisp/files-x.el
+++ b/lisp/files-x.el
@@ -491,6 +491,13 @@ modify-dir-local-variable
                (cons `(,mode . ((,variable . ,value)))
                      variables))))
 
+      ;; Invalidate cache (may be needed if this .dir-locals.el file
+      ;; will be written with the same timestamp as is already present
+      ;; in the cache, see bug#13860).
+      (setq dir-locals-directory-cache
+            (assoc-delete-all (file-name-directory variables-file)
+                              dir-locals-directory-cache))
+
       ;; Insert modified alist of directory-local variables.
       (insert ";;; Directory Local Variables\n")
       (insert ";;; For more information see (info \"(emacs) Directory Variables\")\n\n")


Regards,

/Johan





On Wed, Aug 14 2019, Lars Ingebrigtsen wrote:
> Johan Claesson <johanclaesson@bredband.net> writes:
>
>> Maybe i have misunderstood something but i find the cache
>> mechanism for directory local variables unreliable in one rare
>> case.  If first .dir-locals.el is read and a binding say foo = 1 is
>> inserted in the dir-locals-directory-cache.  And then foo = 2 is
>> written in the same second.  Now next time the dir locals the old
>> binding foo = 1 will be returned.  The cache entry is considered
>> valid when it should not.  
>>
>> Of course it is unlikely that a user is typing so fast that they
>> trigger this :).  But it can be triggered from Lisp.  I found out
>> when playing with a ert test case that was tampering with a dir
>> local.  
>
> (I'm going through old bug reports that have unfortunately gotten no
> responses yet.)
>
>> Here is a recipe for this:
>>
>> (defvar foo nil)
>> (put 'foo 'safe-local-variable 'numberp)
>> (let ((dir (make-temp-file "cache-test" t)))
>>   ;; Create .dir-locals.el with foo = 1.
>>   (with-temp-buffer
>>     (cd dir)
>>     (add-dir-local-variable nil 'foo 1)
>>     (save-buffer)
>>     (kill-buffer))
>>   ;; Read it into dir-locals-directory-cache
>>   ;; and save .dir-locals.el with foo = 2.
>>   (with-temp-buffer
>>     (cd dir)
>>     (make-local-variable 'foo)
>>     (hack-dir-local-variables-non-file-buffer)
>>     (add-dir-local-variable nil 'foo 2)
>>     (save-buffer)
>>     (kill-buffer))
>>   ;; Read it back again.
>>   ;; It should be 2 at this point but is 1 most of the times. 
>>   ;; (At the rare occasion that seconds increase
>>   ;; between the two add-dir-local-variable it returns 1).
>>   (with-temp-buffer
>>     (cd dir)
>>     (make-local-variable 'foo)
>>     (hack-dir-local-variables-non-file-buffer)
>>     (delete-file dir-locals-file)
>>     (delete-directory dir) 
>>     foo))
>
> I'm unable to reproduce this problem in Emacs 27, but perhaps this could
> be a problem if the file system doesn't have sub-second resolution?  Are
> there such file systems still in use (I mean, for something where'd you
> store file with file-local variables)?





  reply	other threads:[~2019-08-18 19:19 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-03 11:01 bug#13860: 24.2; dir-locals-directory-cache unreliable in one rare case Johan Claesson
2019-08-15  6:18 ` Lars Ingebrigtsen
2019-08-18 19:19   ` Johan Claesson [this message]
2019-08-18 22:49     ` Lars Ingebrigtsen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87y2zqs2my.fsf@bredband.net \
    --to=johanclaesson@bredband.net \
    --cc=13860@debbugs.gnu.org \
    --cc=larsi@gnus.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.