aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2016-08-31 11:11:27 +0200
committerLukas Larsson <[email protected]>2016-09-02 09:51:55 +0200
commit7c5f497ab6f4b145554ee884e9fa0ec86246e9ee (patch)
tree70ed27668b160a44ff81cf7c6dca96ecedd58373 /erts/emulator
parentbba0f5924fa9478d41903331a3285f117c112731 (diff)
downloadotp-7c5f497ab6f4b145554ee884e9fa0ec86246e9ee.tar.gz
otp-7c5f497ab6f4b145554ee884e9fa0ec86246e9ee.tar.bz2
otp-7c5f497ab6f4b145554ee884e9fa0ec86246e9ee.zip
erts: Fix child setup signal hander bug
When running the signal handler, the errno has to be restored to its original value, otherwise code running in the same thread may misbehave.
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 */