(stat(...) == -1 || faccessat(...) == -1) && errno == EINTR ?!??
Tobias Bading
tbading@web.de
Sun Feb 14 17:30:50 GMT 2021
Hi Godmar,
thanks a lot for your feedback.
> Bringing up POSIX may not be the most fruitful course of action, and
> asking for compensation in the C library (as in doing an automatic
> restart in the C library system call wrapper) is generally not a good
> idea to my knowledge.
Sorry if my mail sounded like I was trying to point fingers or anything.
I simply chose the GNU libc mailing list because I couldn't find the
definitive answer to the seemingly innocent question "Can stat() or
faccessat() return -1 with errno == EINTR?", neither in their man pages,
some standard spec like POSIX, nor the depth of the internet.
I've been writing software for different UNIXes for a few decades now
and so far I primarily followed the(/my own?) rule "if a man page
doesn't mention EINTR, you don't need to worry about it". If that rule
is incorrect, I have quite a few lines of code to review and wouldn't
even know where to start. XD
EINTR is definitely a very special errno that needs to be handled in
userland, *if* a function is known to return with errno EINTR in (more
or less) specific cases. But there's a ton of ancient userland code that
calls stat() without handling EINTR, probably because the function never
returned EINTR before and no documentation ever claimed that it could.
If that function is able to return with EINTR now, it has the potential
to break a lot of existing code.
> Your choices are, in my opinion:
> - to handle `EINTR` in user mode
Yes, wrapping TEMP_FAILURE_RETRY() macros around the stat() and
faccessat() calls in Emacs' source code did work as a band-aid.
> - to file a bug (and propose a fix) against the kernel.
If the GNU libc devs agree that neither stat() nor faccessat() should
ever return with errno EINTR and this error code is coming directly from
a syscall, then that's the way to go I guess.
> Specifically, inside the kernel, most system calls are restartable
> (and should be restarted if `SA_RESTART` is given), but occasionally
> you find a place where the kernel implementor decided that they can't
> restart the system call, in which case `EINTR` is propagated to user
> land. I've encountered this personally in the past with
> `tcsetattr()`.
> Also, a link to when I brought up a similar issue in 2011 about
tcsetattr():
> http://lkml.iu.edu/hypermail/linux/kernel/1110.1/02954.html
A kernel implementor decides to let EINTR propagate into userland? o.O
In case of tcsetattr() or stat(), wouldn't that be in clear violation of
Linus' "WE DO NOT BREAK USERSPACE!" first rule of kernel maintenance?
(https://lkml.org/lkml/2012/12/23/75)
What happened in the tcsetattr() case? The man page of tcsetattr()
doesn't mention EINTR, did they revert the kernel change?
> You'd need to
> look in https://github.com/torvalds/linux/tree/master/fs/cifs for
> places where they set something to `-EINTR` and then fail to turn it
> into `-ERESTARTSYS` and do not have good reason to do so.
Thanks for the pointers.
Do you know whether -ERESTARTSYS is used to request an unconditional
restart of the system call, or is SA_RESTART specified (or not) in
userland also a factor? If we agree that stat() should never return with
EINTR, than SA_RESTART shouldn't be a factor. (BTW, Emacs is
intentionally not using SA_RESTART in emacs_sigaction_flags() in
src/sysdep.c.)
> PS: This discussion may be helpful
> https://www.spinics.net/lists/stable/msg440182.html - maybe it's your
> bug?
Thanks!!!
I'm running a 5.4 kernel, but since that mail is barely a month old I
have to check whether my current kernel contains that patch.
Tobias
More information about the Libc-help
mailing list