Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20210515150008.GL2546@brightrain.aerifal.cx>
Date: Sat, 15 May 2021 11:00:08 -0400
From: Rich Felker <dalias@...c.org>
To: Dominic Chen <d.c.ddcc@...il.com>
Cc: musl@...ts.openwall.com
Subject: Re: [PATCH] __stdio_write: retry on interrupted system call

On Fri, May 14, 2021 at 09:37:37PM -0400, Dominic Chen wrote:
> I've noticed that my C++ application stops printing to stdout after
> a while, and I didn't know why. It turns out that printing via
> 'std::ostream::operator<<' will eventually call '__stdio_write()',
> which then calls 'writev()'. But, if 'writev()' is interrupted by a
> signal and SA_RESTART is not set, then it will return EINTR, which
> will cause both the 'FILE' structure and the corresponding C++
> stream to be marked bad. I think the current behavior is very
> confusing, so attached is a patch to retry on EINTR.

The current behavior is as specified: all stdio read functions behave
as if by repeated fgetc, and one of the specified errors for fgetc is:

[EINTR]
    The read operation was terminated due to the
    receipt of a signal, and no data was transferred.

Retrying on EINTR would defeat the whole purpose of installing an
interrupting signal handler, which is to break out of operations which
might be blocking indefinitely when a signal is received.

With low-level IO on the fd, the caller can meaningfully handle EINTR
or short reads and later pick up where it left off, if it wants to.
But this is not possible with stdio. For example if the interruption
is in the middle of reading a format field with scanf, there is
nowhere to store the intermediate state. Effectively, it's just an "IO
error" at this layer. Of course if it's a seekable file you could
clear the error flag and seek back to a known location to pick up
later.

Note that EINTR can only happen in programs that actually *want* the
interrupting behavior. If you don't want it, don't install signal
handlers without SA_RESTART.

Rich



> From 6428a3baaf65b26d7b2c4e09d1688a0cb08fa4f7 Mon Sep 17 00:00:00 2001
> From: Dominic Chen <d.c.ddcc@...il.com>
> Date: Fri, 14 May 2021 21:09:33 -0400
> Subject: [PATCH] __stdio_write: retry on interrupted system call
> 
> ---
>  src/stdio/__stdio_write.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/src/stdio/__stdio_write.c b/src/stdio/__stdio_write.c
> index d2d89475..142af0bf 100644
> --- a/src/stdio/__stdio_write.c
> +++ b/src/stdio/__stdio_write.c
> @@ -19,6 +19,8 @@ size_t __stdio_write(FILE *f, const unsigned char *buf, size_t len)
>  			return len;
>  		}
>  		if (cnt < 0) {
> +			if (errno == EINTR)
> +				continue;
>  			f->wpos = f->wbase = f->wend = 0;
>  			f->flags |= F_ERR;
>  			return iovcnt == 2 ? 0 : len-iov[0].iov_len;
> -- 
> 2.25.1
> 

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.