GNU bug report logs -
#72641
31.0.50; "Unlocking file: Invalid argument" when deleting lock file on network file system
Previous Next
Reported by: Michal Nazarewicz <mina86 <at> mina86.com>
Date: Thu, 15 Aug 2024 16:03:02 UTC
Severity: normal
Merged with 70973
Found in versions 29.1, 31.0.50
Done: Paul Eggert <eggert <at> cs.ucla.edu>
Bug is archived. No further changes may be made.
To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 72641 in the body.
You can then email your comments to 72641 AT debbugs.gnu.org in the normal way.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#72641
; Package
emacs
.
(Thu, 15 Aug 2024 16:03:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Michal Nazarewicz <mina86 <at> mina86.com>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Thu, 15 Aug 2024 16:03:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
[Sending this again as a new bug report since #70973 is archived].
On Thu, May 16 2024, Eli Zaretskii wrote:
> I'm not sure we should silently sweep these rare and special cases
> under the carpet. The warning is just a warning, and manually
> deleting the lock file fixes even that.
>
> So I'm not sure we should do anything here, as long as the conclusion
> is that this happened due to a system crash in an opportune moment.
I’m getting the same warning on Linux with Emacs 31.0.50 and it’s not
caused by a crash.
emacs> M-x find-file RET /o/foo RET blah RET
cli> $ ls -l /o/.#foo
cli> -rw------- 1 mpn mpn 0 2024-08-15 16:30 /o/.#foo
emacs> M-x save-buffer RET
emacs> ⛔ Warning (unlock-file): Unlocking file: Invalid argument, /o/foo, ignored
cli> $ ls -l /o/.#foo /o/foo
cli> -rw------- 1 mpn mpn 5 2024-08-15 16:31 /o/foo
cli> -rw------- 1 mpn mpn 0 2024-08-15 16:30 /o/.#foo
The problem appears to be that /o is a network file-system which does
not support symbolic links:
$ mount |grep /o
//192.168.x.x/data on /o type cifs (rw,relatime,vers=3.0,cache=strict,username=mpn,uid=1000,forceuid,gid=1000,forcegid,addr=192.168.x.x,file_mode=0600,dir_mode=0700,soft,nounix,serverino,mapposix,reparse=nfs,rsize=4194304,wsize=4194304,bsize=1048576,retrans=1,echo_interval=60,actimeo=1,closetimeo=1,_netdev)
$ ln -s /o/foo /o/f
ln: failed to create symbolic link '/o/f': Input/output error
I guess Emacs notices that when it tries to create a lock file and falls
back to creating a file, but then it assumes it’s a symlink when trying
to remove it.
---------- >8 ------------------------------------------------------
In GNU Emacs 31.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version
3.24.43, cairo version 1.18.0) of 2024-08-12 built on erwin
Repository revision: 5d69e2916458148159d7f21257f3c4863b868690
Repository branch: HEAD
Windowing system distributor 'The X.Org Foundation', version 11.0.12101011
System Description: Debian GNU/Linux trixie/sid
Configured using:
'configure --prefix=/usr/local --disable-acl
--enable-link-time-optimization --with-native-compilation=aot
--without-dbus --without-gconf --without-gpm --without-gsettings
--without-pop --without-selinux --without-systemd
--without-toolkit-scroll-bars --with-x --with-x-toolkit=gtk3
--with-xinput2 --with-xml2 'CFLAGS=-O2 -mtune=native -march=native
-fstack-protector' 'CPPFLAGS=-O2 -mtune=native -march=native
-fstack-protector' 'CXXFLAGS=-O2 -mtune=native -march=native
-fstack-protector''
Configured features:
CAIRO FREETYPE GIF GLIB GMP GNUTLS HARFBUZZ JPEG LIBXML2 MODULES
NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG SECCOMP SOUND THREADS TIFF WEBP
X11 XDBE XIM XINPUT2 XPM GTK3 ZLIB
Important settings:
value of $LC_COLLATE: C
value of $LANG: en_GB.utf8
locale-coding-system: utf-8-unix
Major mode: Rust
Minor modes in effect:
server-mode: t
flyspell-mode: t
auto-dim-other-buffers-mode: t
global-auto-revert-mode: t
icomplete-mode: t
global-num3-mode: t
num3-mode: t
global-whitespace-mode: t
whitespace-mode: t
global-flyspell-mode: t
delete-selection-mode: t
windmove-mode: t
tooltip-mode: t
global-eldoc-mode: t
eldoc-mode: t
show-paren-mode: t
electric-indent-mode: t
mouse-wheel-mode: t
tool-bar-mode: t
menu-bar-mode: t
file-name-shadow-mode: t
global-font-lock-mode: t
font-lock-mode: t
minibuffer-regexp-mode: t
column-number-mode: t
line-number-mode: t
auto-fill-function: do-auto-fill
transient-mark-mode: t
auto-composition-mode: t
auto-encryption-mode: t
auto-compression-mode: t
Load-path shadows:
/home/mpn/.config/emacs/elpa/transient-20210525.1141/transient hides /usr/local/share/emacs/31.0.50/lisp/transient
~/.config/emacs/custom hides /usr/local/share/emacs/31.0.50/lisp/custom
Features:
(shadow emacsbug mm-archive parse-time iso8601 mule-util image-mode exif
wdired dired-aux pp network-stream nsm mailalias smtpmail textsec
uni-scripts idna-mapping ucs-normalize uni-confusable textsec-check qp
sort mail-extr notmuch notmuch-tree notmuch-jump notmuch-hello wid-edit
notmuch-show notmuch-print notmuch-crypto notmuch-mua notmuch-message
notmuch-draft notmuch-maildir-fcc notmuch-address notmuch-company
notmuch-parser format-spec notmuch-wash diff-mode track-changes coolj
goto-addr icalendar notmuch-tag crm notmuch-lib notmuch-compat pcase
hl-line mm-view mml-smime smime gnutls dig gnus-alias rot13 message
sendmail yank-media puny dired dired-loaddefs rfc822 mml mml-sec epa
derived epg rfc6068 epg-config gnus-util mm-decode mm-bodies mm-encode
mail-parse rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr
mailabbrev mail-utils gmm-utils mailheader calc-alg calc-ext calc-menu
calc calc-loaddefs calc-macs project dabbrev auto-package-update
easy-mmode dash rust-utils rust-mode rust-rustfmt rust-playpen
rust-compile rust-cargo time-date mc-hide-unmatched-lines-mode
mc-mark-more mc-cycle-cursors multiple-cursors-core rect misearch
multi-isearch conf-mode pulse color descr-text server flyspell form-feed
init sgml-mode facemenu dom auto-dim-other-buffers face-remap autorevert
filenotify comp comp-cstr cl-extra help-mode warnings comp-run
comp-common rx icomplete num3-mode disp-table whitespace compile
text-property-search comint ansi-osc ansi-color ring ispell remember
advice browse-kill-ring delsel ffap thingatpt windmove diary-lib
diary-loaddefs cal-menu calendar cal-loaddefs
auto-dim-other-buffers-autoloads avy-autoloads
browse-kill-ring-autoloads csv-mode-autoloads evil-autoloads
gnu-elpa-keyring-update-autoloads gnus-alias-autoloads finder-inf
markdown-mode-autoloads notmuch-autoloads protobuf-mode-autoloads
sed-mode-autoloads info vterm-autoloads package browse-url url url-proxy
url-privacy url-expand url-methods url-history url-cookie
generate-lisp-file url-domsuf url-util mailcap url-handlers url-parse
auth-source cl-seq eieio eieio-core cl-macs icons password-cache json
subr-x map byte-opt gv bytecomp byte-compile url-vars cl-loaddefs cl-lib
early-init rmc iso-transl tooltip cconv eldoc paren electric uniquify
ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win
term/common-win x-dnd touch-screen tool-bar dnd fontset image regexp-opt
fringe tabulated-list replace newcomment text-mode lisp-mode prog-mode
register page tab-bar menu-bar rfn-eshadow isearch easymenu timer select
scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors
frame minibuffer nadvice seq simple cl-generic indonesian philippine
cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao
korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech
european ethiopic indian cyrillic chinese composite emoji-zwj charscript
charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure
cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp
files window text-properties overlay sha1 md5 base64 format env
code-pages mule custom widget keymap hashtable-print-readable backquote
threads inotify dynamic-setting font-render-setting cairo gtk x-toolkit
xinput2 x multi-tty move-toolbar make-network-process native-compile
emacs)
Memory information:
((conses 16 667368 1514832) (symbols 48 33066 15)
(strings 32 118043 64516) (string-bytes 1 3468194) (vectors 16 66157)
(vector-slots 8 1624733 757680) (floats 8 247 2757)
(intervals 56 57621 24687) (buffers 984 58))
---------- 8< ------------------------------------------------------
--
Best regards
ミハウ “𝓶𝓲𝓷𝓪86” ナザレヴイツ
«If at first you don’t succeed, give up skydiving»
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#72641
; Package
emacs
.
(Thu, 15 Aug 2024 17:47:01 GMT)
Full text and
rfc822 format available.
Message #8 received at 72641 <at> debbugs.gnu.org (full text, mbox):
>> From: Michal Nazarewicz <mina86 <at> mina86.com>
>> Date: Thu, 15 Aug 2024 17:41:03 +0200
>>
>> I’m getting the same warning on Linux with Emacs 31.0.50 and it’s not
>> caused by a crash.
>>
>> emacs> M-x find-file RET /o/foo RET blah RET
>> cli> $ ls -l /o/.#foo
>> cli> -rw------- 1 mpn mpn 0 2024-08-15 16:30 /o/.#foo
>> emacs> M-x save-buffer RET
>> emacs> ⛔ Warning (unlock-file): Unlocking file: Invalid argument, /o/foo, ignored
>> cli> $ $ ls -l /o/.#foo /o/foo
>> cli> -rw------- 1 mpn mpn 5 2024-08-15 16:31 /o/foo
>> cli> -rw------- 1 mpn mpn 0 2024-08-15 16:30 /o/.#foo
>>
>> The problem appears to be that /o is a network file-system which does
>> not support symbolic links:
>>
>> $ mount |grep /o
>> //192.168.x.x/data on /o type cifs (rw,relatime,vers=3.0,cache=strict,username=mpn,uid=1000,forceuid,gid=1000,forcegid,addr=192.168.x.x,file_mode=0600,dir_mode=0700,soft,nounix,serverino,mapposix,reparse=nfs,rsize=4194304,wsize=4194304,bsize=1048576,retrans=1,echo_interval=60,actimeo=1,closetimeo=1,_netdev)
>> $ ln -s /o/foo /o/f
>> ln: failed to create symbolic link '/o/f': Input/output error
>>
>> I guess Emacs notices that when it tries to create a lock file and falls
>> back to creating a file, but then it assumes it’s a symlink when trying
>> to remove it.
On Thu, Aug 15 2024, Eli Zaretskii wrote:
> I'm not sure we need to do anything here, either, but maybe Paul
> (CC'ed) has other suggestions or ideas.
The way I see it, Emacs has created those files so Emacs should clean
after itself. Though I’ve looked at it a bit more closely and it’s
weirder than my original guess.
symlink(2) creates the file (as in it creates a regular file rather than
a symbolic link) and returns EIO. create_lock_file reports an error and
does not go into its fallback. This is why the lock file is empty. In
the end, the error comes from current_lock_owner as it tries to parse
the empty file.
The *Warnings* buffer constantly popping up is annoying so I’d love this
to be addressed though to be honest I’m not sure what would be a good
solution. Though I guess you can also argue this is CIFS bug.
--
Best regards
ミハウ “𝓶𝓲𝓷𝓪86” ナザレヴイツ
«If at first you don’t succeed, give up skydiving»
Merged 70973 72641.
Request was from
Paul Eggert <eggert <at> cs.ucla.edu>
to
control <at> debbugs.gnu.org
.
(Thu, 15 Aug 2024 17:54:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#72641
; Package
emacs
.
(Thu, 15 Aug 2024 21:45:02 GMT)
Full text and
rfc822 format available.
Message #13 received at 72641 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
On 2024-08-15 10:44, Michal Nazarewicz wrote:
> The*Warnings* buffer constantly popping up is annoying so I’d love this
> to be addressed though to be honest I’m not sure what would be a good
> solution. Though I guess you can also argue this is CIFS bug.
It's definitely a file system bug. The symlink syscall should never
create a regular file. I suggest reporting the bug to whoever maintains
your file system code.
I don't see any good way to prevent Emacs from creating these
zero-length files on buggy file systems.
That being said, I think Emacs can ignore and remove bad lock files
without introducing more races. I installed the attached into the master
branch and it works for me on your test case (which I introduced
artificially on GNU/Linux). Please give it a try.
The first patches in this series are just setup. The last patch is the
real workaround.
[0001-Fix-unlikely-lock-file-integer-overflow.patch (text/x-patch, attachment)]
[0002-Avoid-some-GC-when-locking-unlocking-files.patch (text/x-patch, attachment)]
[0003-Refactor-current_lock_owner.patch (text/x-patch, attachment)]
[0004-Remove-empty-invalid-lock-files.patch (text/x-patch, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#72641
; Package
emacs
.
(Fri, 16 Aug 2024 01:02:01 GMT)
Full text and
rfc822 format available.
Message #16 received at 72641 <at> debbugs.gnu.org (full text, mbox):
On Thu, Aug 15 2024, Paul Eggert wrote:
> That being said, I think Emacs can ignore and remove bad lock files
> without introducing more races. I installed the attached into the master
> branch and it works for me on your test case (which I introduced
> artificially on GNU/Linux). Please give it a try.
With Emacs from current master, if I open a file, edit it and then kill
the buffer without saving the changes, the lock file is deleted.
However, if I save the file (be it by save-buffer or by killing the
buffer and picking save option), the lock file remains.
I didn’t fully track what is actually happening. It looks like saving
the buffer results in the following:
- lock_file is called
- it calls current_lock_owner
- which deletes the lock file
- and now lock_file creates new lock file
- unlock_file is called
- it calls current_lock_owner
- which return ENOENT for some reason
- the lock file is left alone
In desperation I’ve tried attached patch (it adds `if (!lfinfolen)
return I_OWN_IT`; big diff is because than `if (lfinfolen)` check can be
removed and code dedented) and it worked.
Maybe this is a better approach? Because currently lock_file will delete
the lock file and then create an empty file. With the below file,
lock_file will just notice file is there and do nothing.
From be05054ae47e74192bb3551e83d4afb2ff41f888 Mon Sep 17 00:00:00 2001
From: Michal Nazarewicz <mina86 <at> mina86.com>
Date: Fri, 16 Aug 2024 02:49:55 +0200
Subject: [PATCH] Treat empty lock files as owned by us (bug#72641)
* src/filelock.c (current_lock_owner): Rather then deleting empty lock
files, treat them as if they were owned by us. Previous commit which
deleted the lock file instead resulted in stale lock file remaining when
saving a file.
---
src/filelock.c | 185 ++++++++++++++++++++++++-------------------------
1 file changed, 92 insertions(+), 93 deletions(-)
diff --git a/src/filelock.c b/src/filelock.c
index 1ae57dc7344..f9aac0dc5c5 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -397,110 +397,109 @@ current_lock_owner (lock_info_type *owner, Lisp_Object lfname)
if (lfinfolen < 0)
return errno == ENOENT || errno == ENOTDIR ? 0 : errno;
+ /* The lock file is empty which may be due to buggy file system, e.g.,
+ <https://bugs.gnu.org/72641>. Treat it as us holding the lock. */
+ if (!lfinfolen)
+ return I_OWN_IT;
+
/* If the lock file seems valid, return a value based on its contents. */
- if (lfinfolen)
+ if (MAX_LFINFO < lfinfolen)
+ return ENAMETOOLONG;
+ owner->user[lfinfolen] = 0;
+
+ /* Parse USER <at> HOST.PID:BOOT_TIME. If can't parse, return EINVAL. */
+ /* The USER is everything before the last @. */
+ char *at = memrchr (owner->user, '@', lfinfolen);
+ if (!at)
+ return EINVAL;
+ owner->at = at;
+ char *dot = strrchr (at, '.');
+ if (!dot)
+ return EINVAL;
+ owner->dot = dot;
+
+ /* The PID is everything from the last '.' to the ':' or equivalent. */
+ if (! integer_prefixed (dot + 1))
+ return EINVAL;
+ errno = 0;
+ intmax_t pid = strtoimax (dot + 1, &owner->colon, 10);
+ if (errno == ERANGE)
+ pid = -1;
+
+ /* After the ':' or equivalent, if there is one, comes the boot time. */
+ intmax_t boot_time;
+ char *boot = owner->colon + 1, *lfinfo_end;
+ switch (owner->colon[0])
{
- if (MAX_LFINFO < lfinfolen)
- return ENAMETOOLONG;
- owner->user[lfinfolen] = 0;
-
- /* Parse USER <at> HOST.PID:BOOT_TIME. If can't parse, return EINVAL. */
- /* The USER is everything before the last @. */
- char *at = memrchr (owner->user, '@', lfinfolen);
- if (!at)
- return EINVAL;
- owner->at = at;
- char *dot = strrchr (at, '.');
- if (!dot)
- return EINVAL;
- owner->dot = dot;
+ case 0:
+ boot_time = 0;
+ lfinfo_end = owner->colon;
+ break;
- /* The PID is everything from the last '.' to the ':' or equivalent. */
- if (! integer_prefixed (dot + 1))
+ case '\357':
+ /* Treat "\357\200\242" (U+F022 in UTF-8) like ":" (Bug#24656).
+ This works around a bug in the Linux CIFS kernel client, which can
+ mistakenly transliterate ':' to U+F022 in symlink contents.
+ See <https://bugzilla.redhat.com/show_bug.cgi?id=1384153>. */
+ if (! (boot[0] == '\200' && boot[1] == '\242'))
return EINVAL;
- errno = 0;
- intmax_t pid = strtoimax (dot + 1, &owner->colon, 10);
- if (errno == ERANGE)
- pid = -1;
-
- /* After the ':' or equivalent, if there is one, comes the boot time. */
- intmax_t boot_time;
- char *boot = owner->colon + 1, *lfinfo_end;
- switch (owner->colon[0])
- {
- case 0:
- boot_time = 0;
- lfinfo_end = owner->colon;
- break;
-
- case '\357':
- /* Treat "\357\200\242" (U+F022 in UTF-8) like ":" (Bug#24656).
- This works around a bug in the Linux CIFS kernel client, which can
- mistakenly transliterate ':' to U+F022 in symlink contents.
- See <https://bugzilla.redhat.com/show_bug.cgi?id=1384153>. */
- if (! (boot[0] == '\200' && boot[1] == '\242'))
- return EINVAL;
- boot += 2;
- FALLTHROUGH;
- case ':':
- if (! integer_prefixed (boot))
- return EINVAL;
- boot_time = strtoimax (boot, &lfinfo_end, 10);
- break;
-
- default:
- return EINVAL;
- }
- if (lfinfo_end != owner->user + lfinfolen)
+ boot += 2;
+ FALLTHROUGH;
+ case ':':
+ if (! integer_prefixed (boot))
return EINVAL;
+ boot_time = strtoimax (boot, &lfinfo_end, 10);
+ break;
- char *linkhost = at + 1;
- ptrdiff_t linkhostlen = dot - linkhost;
- Lisp_Object system_name = Fsystem_name ();
- /* If `system-name' returns nil, that means we're in a
- --no-build-details Emacs, and the name part of the link (e.g.,
- .#test.txt -> larsi@.118961:1646577954) is an empty string. */
- bool on_current_host;
- if (NILP (system_name))
- on_current_host = linkhostlen == 0;
- else
- {
- on_current_host = linkhostlen == SBYTES (system_name);
- if (on_current_host)
- {
- /* Protect against the extremely unlikely case of the host
- name containing '@'. */
- char *sysname = SSDATA (system_name);
- for (ptrdiff_t i = 0; i < linkhostlen; i++)
- if (linkhost[i] != (sysname[i] == '@' ? '-' : sysname[i]))
- {
- on_current_host = false;
- break;
- }
- }
- }
- if (!on_current_host)
+ default:
+ return EINVAL;
+ }
+ if (lfinfo_end != owner->user + lfinfolen)
+ return EINVAL;
+
+ char *linkhost = at + 1;
+ ptrdiff_t linkhostlen = dot - linkhost;
+ Lisp_Object system_name = Fsystem_name ();
+ /* If `system-name' returns nil, that means we're in a
+ --no-build-details Emacs, and the name part of the link (e.g.,
+ .#test.txt -> larsi@.118961:1646577954) is an empty string. */
+ bool on_current_host;
+ if (NILP (system_name))
+ on_current_host = linkhostlen == 0;
+ else
+ {
+ on_current_host = linkhostlen == SBYTES (system_name);
+ if (on_current_host)
{
- /* Not on current host. If we wanted to support the check for
- stale locks on remote machines, here's where we'd do it. */
- return ANOTHER_OWNS_IT;
+ /* Protect against the extremely unlikely case of the host
+ name containing '@'. */
+ char *sysname = SSDATA (system_name);
+ for (ptrdiff_t i = 0; i < linkhostlen; i++)
+ if (linkhost[i] != (sysname[i] == '@' ? '-' : sysname[i]))
+ {
+ on_current_host = false;
+ break;
+ }
}
+ }
+ if (!on_current_host)
+ {
+ /* Not on current host. If we wanted to support the check for
+ stale locks on remote machines, here's where we'd do it. */
+ return ANOTHER_OWNS_IT;
+ }
- if (pid == getpid ())
- return I_OWN_IT;
+ if (pid == getpid ())
+ return I_OWN_IT;
- if (VALID_PROCESS_ID (pid)
- && ! (kill (pid, 0) < 0 && errno != EPERM)
- && (boot_time == 0
- || within_one_second (boot_time, get_boot_sec ())))
- return ANOTHER_OWNS_IT;
- }
+ if (VALID_PROCESS_ID (pid)
+ && ! (kill (pid, 0) < 0 && errno != EPERM)
+ && (boot_time == 0
+ || within_one_second (boot_time, get_boot_sec ())))
+ return ANOTHER_OWNS_IT;
- /* The owner process is dead or has a strange pid, or the lock file is empty.
- Try to zap the lockfile. If the lock file is empty, this assumes
- the file system is buggy, e.g., <https://bugs.gnu.org/72641>.
- Emacs never creates empty lock files even temporarily, so removing
- an empty lock file should be harmless. */
+ /* The owner process is dead or has a strange pid.
+ Try to zap the lockfile. */
return emacs_unlink (SSDATA (lfname)) < 0 ? errno : 0;
}
--
2.43.0
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#72641
; Package
emacs
.
(Fri, 16 Aug 2024 03:22:01 GMT)
Full text and
rfc822 format available.
Message #19 received at 72641 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
On 2024-08-15 17:59, Michal Nazarewicz wrote:
> However, if I save the file (be it by save-buffer or by killing the
> buffer and picking save option), the lock file remains....
> - unlock_file is called
> - it calls current_lock_owner
> - which return ENOENT for some reason
> - the lock file is left alone
Obviously current_lock_owner should not return ENOENT if there is an
existing lock file - that would defeat the purpose of having a lock
file. We need to get to the bottom of why current_lock_owner returns ENOENT.
From inspection, current_lock_owner returns ENOENT only if Emacs
notices that the "lock" file is actually an empty regular file (or looks
stale), and calls 'unlink' on it, and 'unlink' fails with errno ==
ENOENT. Is that what's actually happening? You can use a debugger or
'strace' to confirm.
Come to think of it, if 'unlink' fails with errno == ENOENT, that means
there's no lock file so current_lock_owner should return 0. This is true
because of NFS and similar network file systems where unlink can fail
even though it actually removed the file. I installed the attached patch
to fix this; a similar problem exists elsewhere, so this patch fixes all
the instances of it in Emacs master.
With this patch, current_lock_owner should never return ENOENT and we
can move on to the next problem you observe, if there is one.
> In desperation I’ve tried attached patch (it adds `if (!lfinfolen)
> return I_OWN_IT`; big diff is because than `if (lfinfolen)` check can be
> removed and code dedented) and it worked.
Yes, that doesn't sound right; on non-buggy file systems the invalid
lock file would cause races to occur, if I'm reading the code correctly.
Let's see what happens with current master before proceeding in any
direction like that.
[0001-Port-better-to-NFS-unlink.patch (text/x-patch, attachment)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#72641
; Package
emacs
.
(Sat, 17 Aug 2024 20:06:01 GMT)
Full text and
rfc822 format available.
Message #22 received at 72641 <at> debbugs.gnu.org (full text, mbox):
This appears to be network synchronisation issue. I’ve run this
program:
---------- >8 --------------------------------------------------
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
void create(char *path) {
int ret = symlink("dummy", path);
if (ret < 0) {
printf("%s: %d %s\n", path, errno, strerror(errno));
} else {
printf("%s: Ok\n", path);
}
}
int check(char *path) {
char buf[1024];
ssize_t ret = readlink(path, buf, 1024);
if (ret >= 0) {
printf("%s: %.*s\n", path, ret, buf);
return 0;
}
int err = errno;
printf("%s: %d %s\n", path, err, strerror(err));
return err;
}
int main(int argc, char **argv) {
char *path = argc < 2 ? "bar" : argv[1];
create(path);
int loop = 0;
while (check(path) != EINVAL && ++loop < 50) {
usleep(100000);
}
return 0;
}
-------------------------------------------------- 8< ----------
and got the following:
---------- >8 --------------------------------------------------
/o/foo: 5 Input/output error
/o/foo: 2 No such file or directory
/o/foo: 2 No such file or directory
/o/foo: 2 No such file or directory
/o/foo: 2 No such file or directory
/o/foo: 2 No such file or directory
/o/foo: 2 No such file or directory
/o/foo: 2 No such file or directory
/o/foo: 2 No such file or directory
/o/foo: 2 No such file or directory
/o/foo: 2 No such file or directory
/o/foo: 22 Invalid argument
-------------------------------------------------- 8< ----------
It looks like symlink(2) fails with EIO while the server creates
a regular file, however it takes the client to notice another second.
If you’re still interested, here’s strace when I find-file and then
kill-current-buffer without saving:
---------- >8 --------------------------------------------------
faccessat2(AT_FDCWD, "/o/foo", F_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
readlinkat(AT_FDCWD, "/o", 0x7ffec38f7370, 1024) = -1 EINVAL (Invalid argument)
readlinkat(AT_FDCWD, "/o/foo", 0x7ffec38f74d0, 1024) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = -1 ENOENT (No such file or directory)
readlinkat(AT_FDCWD, "/o", 0x7ffec38f72c0, 1024) = -1 EINVAL (Invalid argument)
readlinkat(AT_FDCWD, "/o/foo", 0x7ffec38f7420, 1024) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
readlinkat(AT_FDCWD, "/o/.#foo", 0x7ffec38f13e8, 8193) = -1 ENOENT (No such file or directory)
faccessat2(AT_FDCWD, "/o/foo", F_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
faccessat2(AT_FDCWD, "/o/foo", W_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
faccessat2(AT_FDCWD, "/o/foo", F_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
readlinkat(AT_FDCWD, "/o/foo", 0x7ffec38f7470, 1024) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/o/foo", 0x7ffec38f7750, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/o/foo", 0x7ffec38f77f0, 0) = -1 ENOENT (No such file or directory)
faccessat2(AT_FDCWD, "/o/foo,v", F_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/o/foo", 0x7ffec38f5860, 0) = -1 ENOENT (No such file or directory)
symlink ("mpn <at> erwin.223853:1723847375", "/o/.#foo") = -1 EIO (Input/output error)
readlinkat(AT_FDCWD, "/o/.#foo", 0x7ffec38f5ad8, 8193) = -1 EINVAL (Invalid argument)
openat (AT_FDCWD, "/o/.#foo", O_RDONLY|O_NOFOLLOW|O_CLOEXEC) = 12
read (12, "", 8193) = 0
close (12) = 0
unlink ("/o/.#foo") = 0
-------------------------------------------------- 8< ----------
And this is strace when I find-file and then save-buffer:
---------- >8 --------------------------------------------------
faccessat2(AT_FDCWD, "/o/foo", F_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
readlinkat(AT_FDCWD, "/o", 0x7ffe65452010, 1024) = -1 EINVAL (Invalid argument)
readlinkat(AT_FDCWD, "/o/foo", 0x7ffe65452170, 1024) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = -1 ENOENT (No such file or directory)
readlinkat(AT_FDCWD, "/o", 0x7ffe65451f60, 1024) = -1 EINVAL (Invalid argument)
readlinkat(AT_FDCWD, "/o/foo", 0x7ffe654520c0, 1024) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
readlinkat(AT_FDCWD, "/o/.#foo", 0x7ffe6544c088, 8193) = -1 ENOENT (No such file or directory)
faccessat2(AT_FDCWD, "/o/foo", F_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
faccessat2(AT_FDCWD, "/o/foo", W_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
faccessat2(AT_FDCWD, "/o/foo", F_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
readlinkat(AT_FDCWD, "/o/foo", 0x7ffe65452110, 1024) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/o/foo", 0x7ffe654523f0, 0) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/o/foo", 0x7ffe65452490, 0) = -1 ENOENT (No such file or directory)
faccessat2(AT_FDCWD, "/o/foo,v", F_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/o/foo", 0x7ffe65450500, 0) = -1 ENOENT (No such file or directory)
symlink ("mpn <at> erwin.223938:1723847375", "/o/.#foo") = -1 EIO (Input/output error)
newfstatat(AT_FDCWD, "/o/foo", 0x7ffe65452690, 0) = -1 ENOENT (No such file or directory)
faccessat2(AT_FDCWD, "/o/foo", F_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
faccessat2(AT_FDCWD, "/o/foo,v", F_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_CLOEXEC|O_PATH|O_DIRECTORY) = -1 ENOENT (No such file or directory)
faccessat2(AT_FDCWD, "/o/foo", F_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
faccessat2(AT_FDCWD, "/o/foo", W_OK, AT_EACCESS) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = -1 ENOENT (No such file or directory)
newfstatat(AT_FDCWD, "/o/foo", 0x7ffe6544ff80, 0) = -1 ENOENT (No such file or directory)
symlink ("mpn <at> erwin.223938:1723847375", "/o/.#foo") = -1 EEXIST (File exists)
readlinkat(AT_FDCWD, "/o/.#foo", 0x7ffe65450078, 8193) = -1 EINVAL (Invalid argument)
openat (AT_FDCWD, "/o/.#foo", O_RDONLY|O_NOFOLLOW|O_CLOEXEC) = 12
read (12, "", 8193) = 0
close (12) = 0
unlink ("/o/.#foo") = 0
symlink ("mpn <at> erwin.223938:1723847375", "/o/.#foo") = -1 EIO (Input/output error)
openat (AT_FDCWD, "/o/foo", O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 12
write (12, "ao sneuhta soneht sanoteu snothe"..., 33) = 33
close (12) = 0
newfstatat(AT_FDCWD, "/o/foo", {st_mode=S_IFREG|0600, st_size=33, ...}, 0) = 0
readlinkat(AT_FDCWD, "/o/.#foo", 0x7ffe65450028, 8193) = -1 ENOENT (No such file or directory)
openat (AT_FDCWD, "/o/foo", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = 12
close (12) = 0
-------------------------------------------------- 8< ----------
--
Best regards
ミハウ “𝓶𝓲𝓷𝓪86” ナザレヴイツ
«If at first you don’t succeed, give up skydiving»
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#72641
; Package
emacs
.
(Sat, 17 Aug 2024 22:39:02 GMT)
Full text and
rfc822 format available.
Message #25 received at 72641 <at> debbugs.gnu.org (full text, mbox):
On 2024-08-17 13:03, Michal Nazarewicz wrote:
> It looks like symlink(2) fails with EIO while the server creates
> a regular file, however it takes the client to notice another second.
Yes, it's definitely a file system bug, and I don't see any good way for
Emacs to work around it.
You might try doing your CIFS mount with the mfsymlinks option. See:
https://docs.kernel.org/admin-guide/cifs/usage.html
https://wiki.samba.org/index.php/UNIX_Extensions#Minshall.2BFrench_symlinks
If you're already using mfsymlinks it might be a good time to file a bug
report with your file system supplier.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#72641
; Package
emacs
.
(Sat, 17 Aug 2024 22:57:01 GMT)
Full text and
rfc822 format available.
Message #28 received at 72641 <at> debbugs.gnu.org (full text, mbox):
Paul Eggert wrote:
> You might try doing your CIFS mount with the mfsymlinks option. See:
>
> https://docs.kernel.org/admin-guide/cifs/usage.html
I see from that document that the CIFS client has a tunable cache
timeout. I'd also try setting actimeo=0 and see if that helps.
mike
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#72641
; Package
emacs
.
(Sat, 17 Aug 2024 23:10:02 GMT)
Full text and
rfc822 format available.
Message #31 received at 72641 <at> debbugs.gnu.org (full text, mbox):
Mike Kupfer wrote:
> I'd also try setting actimeo=0 and see if that helps.
Sorry, I was unclear. I meant try actimeo=0 if mfsymlinks doesn't do
the job.
mike
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#72641
; Package
emacs
.
(Sun, 18 Aug 2024 21:18:01 GMT)
Full text and
rfc822 format available.
Message #34 received at 72641 <at> debbugs.gnu.org (full text, mbox):
On Sat, Aug 17 2024, Paul Eggert wrote:
> Yes, it's definitely a file system bug, and I don't see any good way
> for Emacs to work around it.
Yeah, I think this bug can be close. Though if you think the patch I’ve
sent makes sense, I can push it to master as well.
--
Best regards
ミハウ “𝓶𝓲𝓷𝓪86” ナザレヴイツ
«If at first you don’t succeed, give up skydiving»
Reply sent
to
Paul Eggert <eggert <at> cs.ucla.edu>
:
You have taken responsibility.
(Sun, 18 Aug 2024 21:27:02 GMT)
Full text and
rfc822 format available.
Notification sent
to
Michal Nazarewicz <mina86 <at> mina86.com>
:
bug acknowledged by developer.
(Sun, 18 Aug 2024 21:27:02 GMT)
Full text and
rfc822 format available.
Message #39 received at 72641-done <at> debbugs.gnu.org (full text, mbox):
On 2024-08-18 14:15, Michal Nazarewicz wrote:
> On Sat, Aug 17 2024, Paul Eggert wrote:
>> Yes, it's definitely a file system bug, and I don't see any good way
>> for Emacs to work around it.
>
> Yeah, I think this bug can be close. Though if you think the patch I’ve
> sent makes sense, I can push it to master as well.
>
OK, closing the bug report, as the patch you sent in
<https://bugs.gnu.org/72641#16> is problematic for the reasons discussed
in <https://bugs.gnu.org/72641#19>.
Reply sent
to
Paul Eggert <eggert <at> cs.ucla.edu>
:
You have taken responsibility.
(Sun, 18 Aug 2024 21:27:02 GMT)
Full text and
rfc822 format available.
Notification sent
to
Duncan Greatwood <dgreatwood <at> gmail.com>
:
bug acknowledged by developer.
(Sun, 18 Aug 2024 21:27:02 GMT)
Full text and
rfc822 format available.
bug archived.
Request was from
Debbugs Internal Request <help-debbugs <at> gnu.org>
to
internal_control <at> debbugs.gnu.org
.
(Mon, 16 Sep 2024 11:24:06 GMT)
Full text and
rfc822 format available.
This bug report was last modified 277 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.