diff options
author | Lukas Larsson <[email protected]> | 2015-09-14 11:04:22 +0200 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2015-12-15 10:05:45 +0100 |
commit | 123797a395b96b083d895c6ed7f41c56f4eafc78 (patch) | |
tree | ddf7a46e2e0cd9bac7d21a0882b60b0754aba3b1 /erts/emulator | |
parent | 3599b995428032eb26e8b7cc6ac52bc5260ee454 (diff) | |
download | otp-123797a395b96b083d895c6ed7f41c56f4eafc78.tar.gz otp-123797a395b96b083d895c6ed7f41c56f4eafc78.tar.bz2 otp-123797a395b96b083d895c6ed7f41c56f4eafc78.zip |
erts: Handle all EINTR and EAGAIN cases in child setup
Diffstat (limited to 'erts/emulator')
-rw-r--r-- | erts/emulator/sys/unix/erl_child_setup.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/erts/emulator/sys/unix/erl_child_setup.c b/erts/emulator/sys/unix/erl_child_setup.c index 6e0a7c143f..1f7ead0ec3 100644 --- a/erts/emulator/sys/unix/erl_child_setup.c +++ b/erts/emulator/sys/unix/erl_child_setup.c @@ -56,6 +56,8 @@ #include <stdio.h> #include <sys/wait.h> +#define WANT_NONBLOCKING + #include "erl_driver.h" #include "sys_uds.h" @@ -118,7 +120,11 @@ start_new_child(int pipes[]) /* only child executes here */ - if ((res = read(pipes[0], (char*)&size, sizeof(size))) < 0) { + do { + res = read(pipes[0], (char*)&size, sizeof(size)); + } while(res < 0 && (errno == EINTR || errno == ERRNO_BLOCK)); + + if (res <= 0) { ABORT("Failed to read size from %d (%d)", pipes[0], errno); } @@ -128,7 +134,7 @@ start_new_child(int pipes[]) do { if ((res = read(pipes[0], buff + pos, size - pos)) < 0) { - if (errno == EAGAIN || errno == EINTR) + if (errno == ERRNO_BLOCK || errno == EINTR) continue; ABORT("Failed to read %d bytes from %d (%d,%d)", size, pipes[0], res, errno); @@ -187,8 +193,13 @@ start_new_child(int pipes[]) } DEBUG_PRINT("read ack"); - if (read(pipes[0], cbuff, 1) < 1) + do { + res = read(pipes[0], cbuff, 1); + } while(res < 0 && (errno == EINTR || errno == ERRNO_BLOCK)); + if (res < 1) { + errno = EPIPE; goto child_error; + } DEBUG_PRINT("Do that forking business: '%s'\n",cmd); @@ -270,7 +281,10 @@ static void handle_sigchld(int sig) { sys_sigblock(SIGCHLD); while ((buff[0] = waitpid((pid_t)(-1), buff+1, WNOHANG)) > 0) { - if ((res = write(sigchld_pipe[1], buff, sizeof(buff))) <= 0) + do { + res = write(sigchld_pipe[1], buff, sizeof(buff)); + } while (res < 0 && errno == EINTR); + if (res <= 0) ABORT("Failed to write to sigchld_pipe (%d): %d (%d)", sigchld_pipe[1], res, errno); DEBUG_PRINT("Reap child %d (%d)", buff[0], buff[1]); } @@ -391,7 +405,7 @@ main(int argc, char *argv[]) /* We write an ack here, but expect the reply on the pipes[0] inside the fork */ res = sprintf(buff,"GO:%010d:%010d", os_pid, errno); - if (write(pipes[1], buff, res + 1)) + while (write(pipes[1], buff, res + 1) < 0 && errno == EINTR) ; /* remove gcc warning */ sys_sigrelease(SIGCHLD); |