aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2016-09-05 17:24:40 +0200
committerLukas Larsson <[email protected]>2016-09-05 17:24:40 +0200
commit2c9f81b8b030062fb7cbfc4250b2069f73e57cc8 (patch)
tree4606153d4a28cace9f2a0c8c1602a235c06ea553 /erts/emulator
parentbb8d105fd6d5b09097dc64b341d63f0f8d7e8906 (diff)
parent7c5f497ab6f4b145554ee884e9fa0ec86246e9ee (diff)
downloadotp-2c9f81b8b030062fb7cbfc4250b2069f73e57cc8.tar.gz
otp-2c9f81b8b030062fb7cbfc4250b2069f73e57cc8.tar.bz2
otp-2c9f81b8b030062fb7cbfc4250b2069f73e57cc8.zip
Merge branch 'lukas/erts/fix_signalhandler_errno_restore/OTP-13868' into maint
* lukas/erts/fix_signalhandler_errno_restore/OTP-13868: erts: Fix child setup signal hander bug
Diffstat (limited to 'erts/emulator')
-rw-r--r--erts/emulator/sys/unix/erl_child_setup.c14
-rw-r--r--erts/emulator/sys/unix/sys.c12
2 files changed, 19 insertions, 7 deletions
diff --git a/erts/emulator/sys/unix/erl_child_setup.c b/erts/emulator/sys/unix/erl_child_setup.c
index 6b9ddd8da4..69fc6c2879 100644
--- a/erts/emulator/sys/unix/erl_child_setup.c
+++ b/erts/emulator/sys/unix/erl_child_setup.c
@@ -348,7 +348,7 @@ child_error:
* for posterity. */
static void handle_sigchld(int sig) {
- int buff[2], res;
+ int buff[2], res, __preverrno = errno;
sys_sigblock(SIGCHLD);
@@ -362,6 +362,16 @@ static void handle_sigchld(int sig) {
}
sys_sigrelease(SIGCHLD);
+
+ /* We save and restore the original errno as otherwise
+ the thread we are running in may end up with an
+ unexpected errno. An example of when this happened
+ was when the select in main had gotten an EINTR but
+ before the errno was checked the signal handler
+ was called and set errno to ECHILD from waitpid
+ which caused erl_child_setup to abort as it does
+ not expect ECHILD to be set after select */
+ errno = __preverrno;
}
#if defined(__ANDROID__)
@@ -423,7 +433,7 @@ main(int argc, char *argv[])
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
if (sigaction(SIGCHLD, &sa, 0) == -1) {
- perror(0);
+ perror(NULL);
exit(1);
}
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index 6fb86f6dda..089efec3e8 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -715,11 +715,13 @@ static RETSIGTYPE suspend_signal(void)
static RETSIGTYPE suspend_signal(int signum)
#endif
{
- int res;
- int buf[1];
- do {
- res = read(sig_suspend_fds[0], buf, sizeof(int));
- } while (res < 0 && errno == EINTR);
+ int res, buf[1], __errno = errno;
+ do {
+ res = read(sig_suspend_fds[0], buf, sizeof(int));
+ } while (res < 0 && errno == EINTR);
+
+ /* restore previous errno in case read changed it */
+ errno = __errno;
}
#endif /* #ifdef ERTS_SYS_SUSPEND_SIGNAL */