[PATCH] prevent retries on fclose/fflush after write errors

Rich Felker dalias at aerifal.cx
Tue Mar 13 14:58:33 UTC 2012


On Tue, Mar 13, 2012 at 10:30:10AM +0100, Laurent Bercot wrote:
> > Note that I'm claiming the whole "safe_read"/"safe_write" idiom is
> > wrong, and a throwback to the pre-sigaction SysV era when signal() was
> > the only way to install a signal handler and it gave you
> > non-restarting semantics. The idea of an interrupting signal, when set
> > intentionally by a modern application using sigaction, is that EINTR
> > should be treated as a (usually permanent/unrecoverable) failure on
> > blocked in-progress IO operations.
> 
>  Hi Rich,
> 
>  I'm not pronouncing on stdio, since stdio doesn't really mix with
> asynchronous event loops anyway; but in an event-driven program that
> reacts to signals as well as fd events or timeouts, signals can
> arrive at any time and should be handled by the application at the
> same level as any other event, in a normal context, *not* right when
> they arrive in an interrupt context. (Think pselect(), or the self-pipe
> trick.)

I agree that interrupting signals are not very useful for an
event-driven application. This is not their intended usage case.

>  In this case, it is absolutely necessary to protect every read() and
> write() operation, as well as any interruptible system call, against
> EINTR, because EINTR is not reporting a failure, it is only reporting
> the arrival of a signal at an inconvenient time.

EINTR is basically reporting that the user hit Ctrl+C and the
application wants the library routine that was in progress to return
with an error rather than asynchronously exiting, probably because it
has unwritten state that can't be accessed asynchronously for saving.

There is no reason to "protect" reads against EINTR because EINTR
cannot happen unless the application specifically chooses for it to
happen (by installing a non-restarting signal handler). EINTR does not
just randomly happen.

>  This protection can be done at the user level, but there is nothing wrong

My claim is that code doing such protection is wrong and harmful to
begin with.

>  Why not simply let the user set SA_RESTART in the sigaction() call?
> see http://www.skarnet.org/software/skalibs/libstddjb/safewrappers.html

I know of no modern system where this kind of bogus EINTR happens
(SIGSTOP, etc.). Even the proprietary unices fixed it before Linux
did, but they've all been fixed for a long time now. I agree the
standard should be more explicit on this; failure to be explicit, if
you interpret it literally, makes interrupting signals unusable since
you have to wrap all your syscalls with loops and make them behave as
if the signal was a restarting one..

I think the difference in opinion about EINTR comes from two different
ideological camps: one which believes the "Worse is Better" story that
the very existence of EINTR was a bug in early Unix systems, and
another which believes EINTR was/is a feature to allow a program
interrupted during a blocked operation by a (usually user-generated)
signal to terminate or return to an initial state cleanly without
breaking the rules of async signal safety, discarding whatever
intermediate work it was doing.

Think of programs that do something like:
alarm(1);
fgets(buf, sizeof buf, f);

Rich


More information about the uClibc mailing list