Re: Interrupted system call

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Jul 15, 2020 at 2:45 AM Jeff King <peff@xxxxxxxx> wrote:
> On Thu, Jul 02, 2020 at 09:07:46AM +0200, R. Diez wrote:
> > I do not understand why Git is getting these interruptions due to SIGALRM, because SA_RESTART is in place.

It really shouldn't -- that's the whole point of SA_RESTART.

> Delivering EINTR on a non-blocking call seems even more confusing,
> though. I think the "if it can block" is just "you won't even get a
> signal if it's not blocking".
>
> This really _seems_ like a kernel bug, either:
>
>   - openat() does not get the same SA_RESTART treatment as open(); or
>
>   - open() on a network file can get EINTR even with SA_RESTART
>
> But it's quite possible that I'm missing some corner case or historical
> reason that it would need to behave the way you're seeing. It might be
> worth reporting to kernel folks.
>
> -Peff

Right.  This goes way back to pre-v7-Unix signals, as a sort of a
side effect of the implementation.  In ancient times, the kernel
code for the internal wait-for-some-event took a priority number,
and anything below a cutoff value meant "not interrupted by
signals" while anything above it meant "interrupted by signals".
Disk operations were all at PRIBIO which was never interrupted.

This is all quite different in modern systems and hence it's all
adjustable, but in general we like to distinguish between
"operations that will definitely complete fairly quickly"
(normally not interrupted) and "operations that might take
significant amounts of time" (normally interrupted with the option
of restarting the system call).

*Restarting*, though, means exactly that: not *resuming*, but
*restarting*.  So whatever system call is to be interrupted by the
signal *must* be one that can simply be started over from the
beginning.  That means, for instance, that read() or write() can
only be restarted if no data have yet moved.  So if you're in a
read() on a device (e.g., serial port, or tape drive, or whatever)
and have gotten a few bytes, but not yet all you wanted, and then
the system call is to be interrupted by a signal, the read() must
return with a short count.

An open() can be restarted on the assumption that no path names
have been changed.  That's not necessarily a good assumption,
but it's traditional.  The openat() can be restarted for the same
reason (and in fact correct use of openat() can protect against
some pathname issues).  It's up to the programmer to decide
whether to use SA_RESTART, and hence allow this, or not.

Chris



[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux