mailing list of musl libc
 help / color / mirror / Atom feed
* [musl] [PATCH] __stdio_write: retry on interrupted system call
@ 2021-05-15  1:37 Dominic Chen
  2021-05-15 15:00 ` Rich Felker
  0 siblings, 1 reply; 2+ messages in thread
From: Dominic Chen @ 2021-05-15  1:37 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 537 bytes --]

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.

Thanks,

Dominic


[-- Attachment #2: 0001-__stdio_write-retry-on-interrupted-system-call.patch --]
[-- Type: text/plain, Size: 736 bytes --]

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


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

* Re: [musl] [PATCH] __stdio_write: retry on interrupted system call
  2021-05-15  1:37 [musl] [PATCH] __stdio_write: retry on interrupted system call Dominic Chen
@ 2021-05-15 15:00 ` Rich Felker
  0 siblings, 0 replies; 2+ messages in thread
From: Rich Felker @ 2021-05-15 15:00 UTC (permalink / raw)
  To: Dominic Chen; +Cc: musl

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
> 


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

end of thread, other threads:[~2021-05-15 15:00 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-15  1:37 [musl] [PATCH] __stdio_write: retry on interrupted system call Dominic Chen
2021-05-15 15:00 ` Rich Felker

mailing list of musl libc

This inbox may be cloned and mirrored by anyone:

	git clone --mirror http://inbox.vuxu.org/musl

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V1 musl musl/ http://inbox.vuxu.org/musl \
		musl@inbox.vuxu.org
	public-inbox-index musl

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.vuxu.org/vuxu.archive.musl


code repositories for the project(s) associated with this inbox:

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

AGPL code for this site: git clone https://public-inbox.org/public-inbox.git