mailing list of musl libc
 help / color / mirror / code / Atom feed
* [RFC] EINTR and PC loser-ing library design
       [not found] <esmoarexomn.wl-danny.milo+a@gmail.com>
@ 2014-12-08 14:04 ` dannym
  2014-12-08 14:10   ` Rich Felker
  0 siblings, 1 reply; 11+ messages in thread
From: dannym @ 2014-12-08 14:04 UTC (permalink / raw)
  To: musl

Hello,

I just had another hunt for bugs through libraries for EINTR-related woes.
I thought before I patch them, I'd make a proposal here.

EINTR is an ancient wart and like anyone else I have learned to live with it. 
But over the years it has never stopped bothering me. 
And this series of EINTR bugs made me lose confidence that the current way is sustainable.

EINTR serves two purposes:
1) makes the kernel easier by it not having to remember kernel-internal state of a running syscall when a signal arrives.
2) allows the user to see immediately when signals arrive - without having to do unsafe things in the signal handler.

Unfortunately, many routines retry on EINTR without thinking about 2).
Many non-libc routines don't even retry, breaking 1).
So 2) is unusable in practise, even though it's the only sane justification for EINTR to be there in the first place.

What I propose is the following:
- add an intr_handler callback (pointer) to libc, setable by the user, defaulting to one just returning (-1).
- adapt the syscall() interface (~50 system call wrappers of system calls that can return EINTR) to:
    on EINTR, call the callback, and retry the interruptible call only if the callback returned 0.
- adapt TEMP_FAILURE_RETRY(x) to do that as well, for forward compatibility.

The callback is supposed to be provided by the user and supposed to check some flags it set in the signal handler.
Once the callback returns (-1), it shall keep returning (-1) until something is reset by the user manually.

That way, both 1) and 2) work.

Backwards compatibility is ensured since the default callback will cause the syscall wrapper to do the same it always did.
But new programs could now not worry about EINTR except if they wanted to.

I put (way) more detail on <http://www.scratchpost.org/software/%3Carticle%3E/EINTR/>.

What do you think? Do we even want to change this to do the right thing?

If yes, I'd we willing to do the work needed.

If no, can we add just the callback pointer so we have a common interface for everyone else to call?

Thanks,
   Danny


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] EINTR and PC loser-ing library design
  2014-12-08 14:04 ` [RFC] EINTR and PC loser-ing library design dannym
@ 2014-12-08 14:10   ` Rich Felker
  2014-12-08 14:29     ` Laurent Bercot
  0 siblings, 1 reply; 11+ messages in thread
From: Rich Felker @ 2014-12-08 14:10 UTC (permalink / raw)
  To: musl

On Mon, Dec 08, 2014 at 03:04:57PM +0100, dannym@scratchpost.org wrote:
> Hello,
> 
> I just had another hunt for bugs through libraries for EINTR-related woes.
> I thought before I patch them, I'd make a proposal here.
> 
> EINTR is an ancient wart and like anyone else I have learned to live with it. 
> But over the years it has never stopped bothering me. 
> And this series of EINTR bugs made me lose confidence that the current way is sustainable.
> 
> EINTR serves two purposes:
> 1) makes the kernel easier by it not having to remember kernel-internal state of a running syscall when a signal arrives.
> 2) allows the user to see immediately when signals arrive - without having to do unsafe things in the signal handler.
> 
> Unfortunately, many routines retry on EINTR without thinking about 2).
> Many non-libc routines don't even retry, breaking 1).
> So 2) is unusable in practise, even though it's the only sane justification for EINTR to be there in the first place.
> 
> What I propose is the following:
> - add an intr_handler callback (pointer) to libc, setable by the user, defaulting to one just returning (-1).
> - adapt the syscall() interface (~50 system call wrappers of system calls that can return EINTR) to:
>     on EINTR, call the callback, and retry the interruptible call only if the callback returned 0.
> - adapt TEMP_FAILURE_RETRY(x) to do that as well, for forward compatibility.
> 
> The callback is supposed to be provided by the user and supposed to check some flags it set in the signal handler.
> Once the callback returns (-1), it shall keep returning (-1) until something is reset by the user manually.
> 
> That way, both 1) and 2) work.
> 
> Backwards compatibility is ensured since the default callback will cause the syscall wrapper to do the same it always did.
> But new programs could now not worry about EINTR except if they wanted to.
> 
> I put (way) more detail on <http://www.scratchpost.org/software/%3Carticle%3E/EINTR/>.
> 
> What do you think? Do we even want to change this to do the right thing?
> 
> If yes, I'd we willing to do the work needed.
> 
> If no, can we add just the callback pointer so we have a common interface for everyone else to call?

I don't see what problem you're trying to solve. EINTR does not happen
unless you intentionally request it by setting up an interrupting
signal handler, using sigaction() with the SA_RESTART flag clear. In
that case, you want the behavior, i.e. you want blocking functions to
fail when interrupted by the signal being handled.

Retry-on-EINTR loops are generally misguided unless they're in code
that's intended to be using in programs which use interrupting signal
handlers, but which need to reliably complete an operation even if
interrupted.

Rich


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] EINTR and PC loser-ing library design
  2014-12-08 14:10   ` Rich Felker
@ 2014-12-08 14:29     ` Laurent Bercot
  2014-12-08 14:32       ` Rich Felker
  0 siblings, 1 reply; 11+ messages in thread
From: Laurent Bercot @ 2014-12-08 14:29 UTC (permalink / raw)
  To: musl

On 08/12/2014 15:10, Rich Felker wrote:

> I don't see what problem you're trying to solve. EINTR does not happen
> unless you intentionally request it by setting up an interrupting
> signal handler, using sigaction() with the SA_RESTART flag clear.

  What about SIGSTOP, and its cousins SIGTSTP, SIGTTIN and SIGTTOU ?
  Even when you don't request anything, you can receive them. They
stop the process, they don't kill it. What happens when the process
resumes, if it was interrupted in the middle of an interruptible
system call ?


> Retry-on-EINTR loops are generally misguided unless they're in code
> that's intended to be using in programs which use interrupting signal
> handlers, but which need to reliably complete an operation even if
> interrupted.

  And that happens all the time in asynchronous event loops where you
handle signals with a self-pipe. ;)

-- 
  Laurent



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] EINTR and PC loser-ing library design
  2014-12-08 14:29     ` Laurent Bercot
@ 2014-12-08 14:32       ` Rich Felker
  2014-12-08 14:45         ` Laurent Bercot
  0 siblings, 1 reply; 11+ messages in thread
From: Rich Felker @ 2014-12-08 14:32 UTC (permalink / raw)
  To: musl

On Mon, Dec 08, 2014 at 03:29:53PM +0100, Laurent Bercot wrote:
> On 08/12/2014 15:10, Rich Felker wrote:
> 
> >I don't see what problem you're trying to solve. EINTR does not happen
> >unless you intentionally request it by setting up an interrupting
> >signal handler, using sigaction() with the SA_RESTART flag clear.
> 
>  What about SIGSTOP, and its cousins SIGTSTP, SIGTTIN and SIGTTOU ?
>  Even when you don't request anything, you can receive them. They
> stop the process, they don't kill it. What happens when the process
> resumes, if it was interrupted in the middle of an interruptible
> system call ?

The system call restarts (or, formally, it's as if it were never
interrupted; EINTR only applies to signal _handlers_).

> >Retry-on-EINTR loops are generally misguided unless they're in code
> >that's intended to be using in programs which use interrupting signal
> >handlers, but which need to reliably complete an operation even if
> >interrupted.
> 
>  And that happens all the time in asynchronous event loops where you
> handle signals with a self-pipe. ;)

Only if you have installed interrupting signal handlers.

Rich


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] EINTR and PC loser-ing library design
  2014-12-08 14:32       ` Rich Felker
@ 2014-12-08 14:45         ` Laurent Bercot
  2014-12-08 15:00           ` Rich Felker
  2014-12-08 15:18           ` dannym
  0 siblings, 2 replies; 11+ messages in thread
From: Laurent Bercot @ 2014-12-08 14:45 UTC (permalink / raw)
  To: musl

On 08/12/2014 15:32, Rich Felker wrote:

> The system call restarts (or, formally, it's as if it were never
> interrupted; EINTR only applies to signal _handlers_).

  Could you please provide a pointer to the specification that
guarantees this ? I've never been able to find a normative text that
ensures you will never get EINTR unless you explicitly install a
signal handler without SA_RESTART.


>>   And that happens all the time in asynchronous event loops where you
>> handle signals with a self-pipe. ;)
>
> Only if you have installed interrupting signal handlers.

  Which basically means any signal except SIGCHLD.

-- 
  Laurent



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] EINTR and PC loser-ing library design
  2014-12-08 14:45         ` Laurent Bercot
@ 2014-12-08 15:00           ` Rich Felker
  2014-12-08 15:09             ` Rich Felker
  2014-12-08 15:18           ` dannym
  1 sibling, 1 reply; 11+ messages in thread
From: Rich Felker @ 2014-12-08 15:00 UTC (permalink / raw)
  To: musl

On Mon, Dec 08, 2014 at 03:45:33PM +0100, Laurent Bercot wrote:
> On 08/12/2014 15:32, Rich Felker wrote:
> 
> >The system call restarts (or, formally, it's as if it were never
> >interrupted; EINTR only applies to signal _handlers_).
> 
>  Could you please provide a pointer to the specification that
> guarantees this ? I've never been able to find a normative text that
> ensures you will never get EINTR unless you explicitly install a
> signal handler without SA_RESTART.

I've had a hard time pinning it down too, but that's what all modern
(e.g. modern enough to have a working sigaction) implementations do,
and it's the obviously correct behavior. I would consider making a
request for clarification here, but after what happened with the C
locale issue, I'd kinda fear some trolls would appear and insist that
EINTR be allowed to happen for no good reason. :(

> >>  And that happens all the time in asynchronous event loops where you
> >>handle signals with a self-pipe. ;)
> >
> >Only if you have installed interrupting signal handlers.
> 
>  Which basically means any signal except SIGCHLD.

No. Interrupting means "installed without SA_RESTART". It has nothing
to do with which signal it is, but rather how you installed the
handler.

Rich


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] EINTR and PC loser-ing library design
  2014-12-08 15:00           ` Rich Felker
@ 2014-12-08 15:09             ` Rich Felker
  0 siblings, 0 replies; 11+ messages in thread
From: Rich Felker @ 2014-12-08 15:09 UTC (permalink / raw)
  To: musl

On Mon, Dec 08, 2014 at 10:00:31AM -0500, Rich Felker wrote:
> On Mon, Dec 08, 2014 at 03:45:33PM +0100, Laurent Bercot wrote:
> > On 08/12/2014 15:32, Rich Felker wrote:
> > 
> > >The system call restarts (or, formally, it's as if it were never
> > >interrupted; EINTR only applies to signal _handlers_).
> > 
> >  Could you please provide a pointer to the specification that
> > guarantees this ? I've never been able to find a normative text that
> > ensures you will never get EINTR unless you explicitly install a
> > signal handler without SA_RESTART.
> 
> I've had a hard time pinning it down too, but that's what all modern
> (e.g. modern enough to have a working sigaction) implementations do,
> and it's the obviously correct behavior. I would consider making a
> request for clarification here, but after what happened with the C
> locale issue, I'd kinda fear some trolls would appear and insist that
> EINTR be allowed to happen for no good reason. :(

The closest I can find is XSH 2.4.4 Signal Effects on Other Functions:

    Signals affect the behavior of certain functions defined by this
    volume of POSIX.1-2008 if delivered to a process while it is
    executing such a function. If the action of the signal is to
    terminate the process, the process shall be terminated and the
    function shall not return. If the action of the signal is to stop
    the process, the process shall stop until continued or terminated.
    Generation of a SIGCONT signal for the process shall cause the
    process to be continued, and the original function shall continue
    at the point the process was stopped. If the action of the signal
    is to invoke a signal-catching function, the signal-catching
    function shall be invoked; in this case the original function is
    said to be "interrupted" by the signal. If the signal-catching
    function executes a return statement, the behavior of the
    interrupted function shall be as described individually for that
    function, except as noted for unsafe functions. Signals that are
    ignored shall not affect the behavior of any function; signals
    that are blocked shall not affect the behavior of any function
    until they are unblocked and then delivered, except as specified
    for the sigpending() and sigwait() functions.

The above text seems to be what defines the concept of "interrupted",
and it's in terms of a "signal-catching function". The behavior "as
described individually for that function" is usually to fail with
EINTR, but it's overridden by the text of the sigaction function which
defines SA_RESTART to automatically restart functions interrupted in
this sense.

Rich


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] EINTR and PC loser-ing library design
  2014-12-08 14:45         ` Laurent Bercot
  2014-12-08 15:00           ` Rich Felker
@ 2014-12-08 15:18           ` dannym
  2014-12-08 15:28             ` Rich Felker
  1 sibling, 1 reply; 11+ messages in thread
From: dannym @ 2014-12-08 15:18 UTC (permalink / raw)
  To: musl

Hello,

SysV msgrcv (POSIX.1-2001) explicitly states that it never automatically restarts the syscall, it also mentions SA_RESTART to be of no effect for it. So one can always receive EINTR, SA_RESTART or not.

--
   Danny


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] EINTR and PC loser-ing library design
  2014-12-08 15:18           ` dannym
@ 2014-12-08 15:28             ` Rich Felker
  2014-12-08 15:49               ` Laurent Bercot
  0 siblings, 1 reply; 11+ messages in thread
From: Rich Felker @ 2014-12-08 15:28 UTC (permalink / raw)
  To: musl

On Mon, Dec 08, 2014 at 04:18:48PM +0100, dannym@scratchpost.org wrote:
> Hello,
> 
> SysV msgrcv (POSIX.1-2001) explicitly states that it never
> automatically restarts the syscall, it also mentions SA_RESTART to
> be of no effect for it. So one can always receive EINTR, SA_RESTART
> or not.

I don't see any such documentation that it ignores SA_RESTART in
POSIX, looking at both Issue 7 (2008) and Issue 6. What document are
you looking at for it?

The only such exception I'm aware of is that POSIX allows, but does
not require, select to fail with EINTR even when SA_RESTART is used.
This is fairly inconsequential since select is almost always used in a
manner where failure results in a retry.

Rich


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] EINTR and PC loser-ing library design
  2014-12-08 15:28             ` Rich Felker
@ 2014-12-08 15:49               ` Laurent Bercot
  2014-12-08 16:00                 ` Rich Felker
  0 siblings, 1 reply; 11+ messages in thread
From: Laurent Bercot @ 2014-12-08 15:49 UTC (permalink / raw)
  To: musl

On 08/12/2014 16:28, Rich Felker wrote:
> The only such exception I'm aware of is that POSIX allows, but does
> not require, select to fail with EINTR even when SA_RESTART is used.

  What do you say of poll ?
  
	The poll() function shall fail if:
	[EINTR]
	     A signal was caught during poll().

  Note that it is "shall", not "may".

  One may argue that the SA_RESTART behaviour has priority over "poll() shall
fail with EINTR if a signal is caught", as with other functions such as
read(), but one may also argue that, just as with select(), it makes perfect
sense to *not* restart poll() when a signal is caught, since time has elapsed
since the original call and the application may want to update the timeout
values, so the exception that applies to select should also apply to poll.

-- 
  Laurent



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] EINTR and PC loser-ing library design
  2014-12-08 15:49               ` Laurent Bercot
@ 2014-12-08 16:00                 ` Rich Felker
  0 siblings, 0 replies; 11+ messages in thread
From: Rich Felker @ 2014-12-08 16:00 UTC (permalink / raw)
  To: musl

On Mon, Dec 08, 2014 at 04:49:00PM +0100, Laurent Bercot wrote:
> On 08/12/2014 16:28, Rich Felker wrote:
> >The only such exception I'm aware of is that POSIX allows, but does
> >not require, select to fail with EINTR even when SA_RESTART is used.
> 
>  What do you say of poll ?
> 	The poll() function shall fail if:
> 	[EINTR]
> 	     A signal was caught during poll().
> 
>  Note that it is "shall", not "may".
> 
>  One may argue that the SA_RESTART behaviour has priority over "poll() shall
> fail with EINTR if a signal is caught", as with other functions such as
> read(), but one may also argue that, just as with select(), it makes perfect
> sense to *not* restart poll() when a signal is caught, since time has elapsed
> since the original call and the application may want to update the timeout
> values, so the exception that applies to select should also apply to poll.

Since poll does not have explicit text overriding the text on
SA_RESTART, my understanding is that it's required to obey SA_RESTART.
However it's unclear because most functions which have EINTR as a
specified error use the phrase "the function was interrupted
[before]..." (in particular, the word "interrupted" appears) whereas
the text for poll merely says "a signal was caught". This should
probably be clarified. Note that the Linux behavior is that poll
restarts automatically. I'm not sure about select.

Rich


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-12-08 16:00 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <esmoarexomn.wl-danny.milo+a@gmail.com>
2014-12-08 14:04 ` [RFC] EINTR and PC loser-ing library design dannym
2014-12-08 14:10   ` Rich Felker
2014-12-08 14:29     ` Laurent Bercot
2014-12-08 14:32       ` Rich Felker
2014-12-08 14:45         ` Laurent Bercot
2014-12-08 15:00           ` Rich Felker
2014-12-08 15:09             ` Rich Felker
2014-12-08 15:18           ` dannym
2014-12-08 15:28             ` Rich Felker
2014-12-08 15:49               ` Laurent Bercot
2014-12-08 16:00                 ` Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).