mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Rich Felker <dalias@libc.org>
To: Dominic Chen <d.c.ddcc@gmail.com>
Cc: musl@lists.openwall.com
Subject: Re: [musl] [PATCH] __stdio_write: retry on interrupted system call
Date: Sat, 15 May 2021 11:00:08 -0400	[thread overview]
Message-ID: <20210515150008.GL2546@brightrain.aerifal.cx> (raw)
In-Reply-To: <6f1116b7-0124-6c56-d149-2625049708f1@gmail.com>

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@gmail.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
> 


      reply	other threads:[~2021-05-15 15:00 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-15  1:37 Dominic Chen
2021-05-15 15:00 ` Rich Felker [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210515150008.GL2546@brightrain.aerifal.cx \
    --to=dalias@libc.org \
    --cc=d.c.ddcc@gmail.com \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).