From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-3.3 required=5.0 tests=MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 14976 invoked from network); 15 May 2021 15:00:29 -0000 Received: from mother.openwall.net (195.42.179.200) by inbox.vuxu.org with ESMTPUTF8; 15 May 2021 15:00:29 -0000 Received: (qmail 27812 invoked by uid 550); 15 May 2021 15:00:27 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: musl@lists.openwall.com Received: (qmail 27794 invoked from network); 15 May 2021 15:00:26 -0000 Date: Sat, 15 May 2021 11:00:08 -0400 From: Rich Felker To: Dominic Chen Cc: musl@lists.openwall.com Message-ID: <20210515150008.GL2546@brightrain.aerifal.cx> References: <6f1116b7-0124-6c56-d149-2625049708f1@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <6f1116b7-0124-6c56-d149-2625049708f1@gmail.com> User-Agent: Mutt/1.5.21 (2010-09-15) Subject: Re: [musl] [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 > 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 >