From c232329664cb216997cae2363cd2d10fd40b161a Mon Sep 17 00:00:00 2001 From: Iblis Lin Date: Sun, 9 Jul 2017 05:48:43 +0800 Subject: [PATCH] restart `open_cloexec` manually to deal with EINTR (interrupted system call) on `open` --- src/support/ios.c | 22 ++++++++++++++++++---- test/file.jl | 22 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/support/ios.c b/src/support/ios.c index 70af4078f6e9e..719f3fa0a307f 100644 --- a/src/support/ios.c +++ b/src/support/ios.c @@ -874,19 +874,30 @@ static void _ios_init(ios_t *s) /* stream object initializers. we do no allocation. */ #if !defined(_OS_WINDOWS_) +/* + * NOTE: we do not handle system call restart in this function, + * please do it manually: + * + * do + * open_cloexec(...) + * while (-1 == fd && _enonfatal(errno)) + */ static int open_cloexec(const char *path, int flags, mode_t mode) { #ifdef O_CLOEXEC - static int no_cloexec=0; + static int no_cloexec = 0; if (!no_cloexec) { set_io_wait_begin(1); int fd = open(path, flags | O_CLOEXEC, mode); set_io_wait_begin(0); + if (fd != -1) return fd; if (errno != EINVAL) return -1; + + /* O_CLOEXEC not supported. */ no_cloexec = 1; } #endif @@ -918,12 +929,15 @@ ios_t *ios_file(ios_t *s, const char *fname, int rd, int wr, int create, int tru #else // The mode of the created file is (mode & ~umask), which resolves with // default umask to u=rw,g=r,o=r - fd = open_cloexec(fname, flags, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + do + fd = open_cloexec(fname, flags, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + while (-1 == fd && _enonfatal(errno)); #endif - s = ios_fd(s, fd, 1, 1); if (fd == -1) goto open_file_err; + + s = ios_fd(s, fd, 1, 1); if (!rd) s->readable = 0; if (!wr) diff --git a/test/file.jl b/test/file.jl index 527fadcbaa7e6..0080d783d5d60 100644 --- a/test/file.jl +++ b/test/file.jl @@ -1134,3 +1134,25 @@ end test_13559() end @test_throws ArgumentError mkpath("fakepath",-1) + +# issue #22566 +if !Sys.iswindows() + function test_22566() + fn = tempname() + run(`mkfifo $fn`) + + script = "x = open(\"$fn\", \"w\"); close(x)" + cmd = `$(Base.julia_cmd()) --startup-file=no -e $script` + open(pipeline(cmd, stderr=STDERR)) + + r = open(fn, "r") + close(r) + + rm(fn) + end + + # repeat opening/closing fifo file, ensure no EINTR popped out + for i ∈ 1:50 + test_22566() + end +end # !Sys.iswindows