Skip to content

Commit

Permalink
restart open_cloexec manually
Browse files Browse the repository at this point in the history
to deal with EINTR (interrupted system call) on `open`
  • Loading branch information
iblislin committed Jul 13, 2017
1 parent 9c1d1b8 commit c232329
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 4 deletions.
22 changes: 18 additions & 4 deletions src/support/ios.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
22 changes: 22 additions & 0 deletions test/file.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit c232329

Please sign in to comment.