Emacs の bug

% su
# touch /tmp/foo
# chmod 644 /tmp/foo
C-d
% emacs -nw -Q

として、 /su::/tmp/foo を開いてなんか打って保存。 再度、キーを打つと
「foo changed on disk; really edit the buffer? (y, n, r or C-h) 」 と聞かれる。

このメッセージは ask-user-about-supersession-threat() のもの。 insdel.c の prepare_to_modify_buffer() から呼び出されている。

結局、 (verify-visited-file-modtime (current-buffer)) が save 直後にも関らず nil を返しているのがおかしいことがわかる。

そして、つらつらとたどっていくと tramp-handle-verify-visited-file-modtime() までいきつくけれど、 (visited-file-modtime) が (-1 65535) なのが結局の原因。

一度、 (set-visited-file-modtime) してしまえば自由に書けるようになるので advice なり hook なりしてやればまぁ解決。

だけど、根本の原因を追っていきたい。 open 直後は (visited-file-modtime) が普通の値を返すので、 C-x C-s したあたりが問題。

M-x debug-on-entry set-visited-file-modtime で C-x C-s。 tramp-handle-write-region() で (nth 5 (file-attributes filename)) が nil を返してるのがいけない。

tramp-handle-file-attributes() が cache を見て、 hit しなかったら実際に見に行くという処理をしている。ここで file が存在しないと nil を返すのだけど、 Emacs の書きこみかたは foo を foo~ に rename してから foo に書き出すみたいなことをしている(はず)。 だから、 file が存在しなかった時に nil が出る。 これがその後も cache されてるのがいけないのだと思う…。

さてはてどうしたものか…。

;; eldoc-mode おもしろい