Subject: bug#13149: 24.3.50; Emacs thinks file was changed outside Emacs, but it was not

From: Paul Eggert <[email-masked]>
Date: Tue, 15 Jan 2013 14:38:16 -0800

On 01/15/13 14:11, Dmitry Gutov wrote:

> Here you go:

Sorry, what scenario are you using for that?

Here's what I get when I run "src/emacs -Q /tmp/r" and type "a C-x C-s b".
In this transcript I indicate exactly when I typed each character.

fileio.c:3573: stat_mtime=1358285891.979499498
fileio.c:3573: stat_mtime=1358185278.123368557
dired.c:958: stat_mtime=1358285832.923323363
dired.c:958: stat_mtime=1358285832.923323363
fileio.c:3573: stat_mtime=1339474634.000000000
fileio.c:3573: stat_mtime=1357144798.955079131
lread.c:1228: stat_mtime=1357144798.939079049
lread.c:1228: stat_mtime=1358185424.004185658
dired.c:958: stat_mtime=1358288328.739209633
dired.c:958: stat_mtime=1358288328.739209633
fileio.c:3573: stat_mtime=1358288328.739209633
fileio.c:3363: stat_mtime=1358288328.739209633
fileio.c:3363: stat_mtime=1358288344.827280766
a
fileio.c:5350: stat_mtime=1358288328.739209633
C-x C-s
fileio.c:5350: stat_mtime=1358288328.739209633
fileio.c:5350: stat_mtime=1358288328.739209633
fileio.c:5011: stat_mtime=1358288369.760392065
dired.c:958: stat_mtime=1358288369.760392065
b
fileio.c:5350: stat_mtime=1358288369.760392065

You're evidently getting different behavior, since you don't see
lread.c at all, for example.  If I'm guessing right, I think the key
sequence in your transcript is here:

fileio.c:5359: stat_mtime=1358287604.023708900
fileio.c:5020: stat_mtime=1358287610.000000000
dired.c:958: stat_mtime=1358287613.927966600
fileio.c:5359: stat_mtime=1358287613.927966600

and that this corresponds to the last 5 lines of my transcript.

What happens if you apply the following patch as well?
Does it cause Emacs to output "fstat and lstat disagree!"?

=== modified file 'src/fileio.c'
--- src/fileio.c	2013-01-15 10:14:31 +0000
+++ src/fileio.c	2013-01-15 22:35:57 +0000
@@ -5017,6 +5017,20 @@ This calls `write-region-annotate-functi
   if (emacs_close (desc) < 0)
     ok = 0, save_errno = errno;
 
+  if (ok && visiting)
+    {
+      struct stat st1;
+      EMACS_TIME modtime1;
+      if (lstat (fn, &st1) != 0)
+	perror (fn);
+      else
+	{
+	  modtime1 = get_stat_mtime (&st1);
+	  if (! EMACS_TIME_EQ (modtime, modtime1))
+	    fprintf (stderr, "fstat and lstat disagree!\n");
+	}
+    }
+
   /* Discard the unwind protect for close_file_unwind.  */
   specpdl_ptr = specpdl + count1;