Måns Rullgård <m...@mansr.com> wrote: > The return value and ft->tell_off will be wrong in case the fwrite() was > restarted.
Right, updated patch (covers fread + fflush) below; but still somewhere else is hitting EINTR... I'm still alive for now, but not feeling great about it :< > What did you do that caused the EINTR error? SIGWINCH -------8<------- Subject: [PATCH] WIP EINTR handling Still incomplete, SIGWINCH in a complex pipeline (sox -M "|sox ..." "|sox ..." -p) is still causing problems for me even with this patch. Not sure how much time I can devote to tracking more of it down of if I'll just setsid the parent script and call it a day since I fear this can turn into a long-term whack-a-mole situation... --- src/formats.c | 6 ++++- src/formats_i.c | 59 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/formats.c b/src/formats.c index 3fcf4382..31ab99f8 100644 --- a/src/formats.c +++ b/src/formats.c @@ -370,6 +370,10 @@ static sox_bool is_url(char const * text) /* detects only wget-supported URLs */ static int xfclose(FILE * file, lsx_io_type io_type) { + int ret; + do { + ret = fflush(file); + } while (ret == EOF && errno == EINTR); return #ifdef HAVE_POPEN io_type != lsx_io_file? pclose(file) : @@ -1064,7 +1068,7 @@ int sox_close(sox_format_t * ft) if (ft->fp == stdin) { sox_globals.stdin_in_use_by = NULL; } else if (ft->fp == stdout) { - fflush(stdout); + lsx_flush(ft); sox_globals.stdout_in_use_by = NULL; } else if (ft->fp) { xfclose(ft->fp, ft->io_type); diff --git a/src/formats_i.c b/src/formats_i.c index 7048040d..c4ead348 100644 --- a/src/formats_i.c +++ b/src/formats_i.c @@ -95,11 +95,24 @@ int lsx_check_read_params(sox_format_t * ft, unsigned channels, */ size_t lsx_readbuf(sox_format_t * ft, void *buf, size_t len) { - size_t ret = fread(buf, (size_t) 1, len, (FILE*)ft->fp); - if (ret != len && ferror((FILE*)ft->fp)) - lsx_fail_errno(ft, errno, "lsx_readbuf"); - ft->tell_off += ret; - return ret; + FILE *fp = (FILE*)ft->fp; + + while (1) { + size_t ret = fread(buf, 1, len, fp); + ft->tell_off += ret; + + if (ret) + return ret; + + if (feof(fp)) + break; + if (ferror(fp) && errno != EINTR) { + lsx_fail_errno(ft, errno, "lsx_readbuf"); + break; + } + } + + return 0; } /* Skip input without seeking. */ @@ -129,13 +142,29 @@ int lsx_padbytes(sox_format_t * ft, size_t n) */ size_t lsx_writebuf(sox_format_t * ft, void const * buf, size_t len) { - size_t ret = fwrite(buf, (size_t) 1, len, (FILE*)ft->fp); - if (ret != len) { - lsx_fail_errno(ft, errno, "error writing output file"); - clearerr((FILE*)ft->fp); /* Allows us to seek back to write header */ + FILE *fp = (FILE*)ft->fp; + const char *c = (const char *)buf; + sox_uint64_t orig_off = ft->tell_off; + + while (len) { + size_t ret = fwrite(c, 1, len, fp); + + ft->tell_off += ret; + c += ret; + len -= ret; + if (len && ferror(fp)) { + if (errno == EINTR) { + clearerr(fp); + /* retry */ + } else { + lsx_fail_errno(ft, errno, "error writing output file"); + clearerr(fp); /* Allows us to seek back to write header */ + break; + } + } } - ft->tell_off += ret; - return ret; + + return ft->tell_off - orig_off; } sox_uint64_t lsx_filelength(sox_format_t * ft) @@ -148,7 +177,13 @@ sox_uint64_t lsx_filelength(sox_format_t * ft) int lsx_flush(sox_format_t * ft) { - return fflush((FILE*)ft->fp); + int ret; + + do { + ret = fflush((FILE *)ft->fp); + } while (ret == EOF && errno == EINTR); + + return ret; } off_t lsx_tell(sox_format_t * ft) _______________________________________________ SoX-devel mailing list SoX-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sox-devel