src: reset signal handler to SIG_DFL on FreeBSD
authorFedor Indutny <fedor@indutny.com>
Fri, 20 Mar 2015 05:03:34 +0000 (22:03 -0700)
committerFedor Indutny <fedor@indutny.com>
Fri, 20 Mar 2015 21:10:35 +0000 (14:10 -0700)
FreeBSD has a nasty bug with SA_RESETHAND reseting the SA_SIGINFO,
that is in turn set for a libthr wrapper. This leads to a crash.
Work around the issue by manually setting SIG_DFL in the signal
handler.

Fix: https://github.com/joyent/node/issues/9326
PR-URL: https://github.com/iojs/io.js/pull/1218
Reviewed-By: Johan Bergström <bugs@bergstroem.nu>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
src/node.cc
test/parallel/test-regress-GH-node-9326.js [new file with mode: 0644]

index 42b690f..b8decf8 100644 (file)
@@ -2877,6 +2877,13 @@ static void AtExit() {
 
 static void SignalExit(int signo) {
   uv_tty_reset_mode();
+#ifdef __FreeBSD__
+  // FreeBSD has a nasty bug, see RegisterSignalHandler for details
+  struct sigaction sa;
+  memset(&sa, 0, sizeof(sa));
+  sa.sa_handler = SIG_DFL;
+  CHECK_EQ(sigaction(signo, &sa, nullptr), 0);
+#endif
   raise(signo);
 }
 
@@ -3257,7 +3264,12 @@ static void RegisterSignalHandler(int signal,
   struct sigaction sa;
   memset(&sa, 0, sizeof(sa));
   sa.sa_handler = handler;
+#ifndef __FreeBSD__
+  // FreeBSD has a nasty bug with SA_RESETHAND reseting the SA_SIGINFO, that is
+  // in turn set for a libthr wrapper. This leads to a crash.
+  // Work around the issue by manually setting SIG_DFL in the signal handler
   sa.sa_flags = reset_handler ? SA_RESETHAND : 0;
+#endif
   sigfillset(&sa.sa_mask);
   CHECK_EQ(sigaction(signal, &sa, nullptr), 0);
 }
diff --git a/test/parallel/test-regress-GH-node-9326.js b/test/parallel/test-regress-GH-node-9326.js
new file mode 100644 (file)
index 0000000..15a2abb
--- /dev/null
@@ -0,0 +1,12 @@
+var assert = require('assert');
+var child_process = require('child_process');
+
+// NOTE: Was crashing on FreeBSD
+var cp = child_process.spawn(process.execPath, [
+  '-e',
+  'process.kill(process.pid, "SIGINT")'
+]);
+
+cp.on('exit', function(code) {
+  assert.notEqual(code, 0);
+});