From d6572f074a899e692a8233256d48901c1ee5a8aa Mon Sep 17 00:00:00 2001
From: Konstantin Osipov <kostja@tarantool.org>
Date: Tue, 1 May 2012 10:20:42 +0400
Subject: [PATCH] A fix for https://bugs.launchpad.net/tarantool/+bug/992171

A fix for https://bugs.launchpad.net/tarantool/+bug/992171
"SAVE SNAPSHOT process (dumper) does not respond to signals"

Reset the signal mask/handler after a fork to their defaults.
Make sure that when the snapshot dumper process is terminated
with a signal, we report it back to the user.

No test case since it would be hard to do a concurrent
test in our framework yet.
---
 include/tarantool_pthread.h |  5 +++++
 src/log_io.m                |  2 +-
 src/tarantool.m             | 30 +++++++++++++++++++++++++++++-
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/include/tarantool_pthread.h b/include/tarantool_pthread.h
index e1f781dd52..41094a031a 100644
--- a/include/tarantool_pthread.h
+++ b/include/tarantool_pthread.h
@@ -149,5 +149,10 @@
 	tt_pthread_error(e);			\
 })
 
+#define tt_pthread_atfork(prepare, parent, child)\
+({	int e = pthread_atfork(prepare, parent, child);\
+	tt_pthread_error(e);			\
+})
+
 
 #endif /* TARANTOOL_PTHREAD_H_INCLUDED */
diff --git a/src/log_io.m b/src/log_io.m
index ac1ef27c48..684842164a 100644
--- a/src/log_io.m
+++ b/src/log_io.m
@@ -1254,7 +1254,7 @@ wal_writer_child()
 static void
 wal_writer_init_once()
 {
-	pthread_atfork(NULL, NULL, wal_writer_child);
+	tt_pthread_atfork(NULL, NULL, wal_writer_child);
 }
 
 /**
diff --git a/src/tarantool.m b/src/tarantool.m
index 8df1136927..b9a397193e 100644
--- a/src/tarantool.m
+++ b/src/tarantool.m
@@ -57,6 +57,7 @@
 #include <util.h>
 #include <third_party/gopt/gopt.h>
 #include <cfg/warning.h>
+#include "tarantool_pthread.h"
 
 
 static pid_t master_pid;
@@ -277,7 +278,8 @@ snapshot(void *ev, int events __attribute__((unused)))
 		 */
 		wait_for_child(p);
 		assert(p == fiber->cw.rpid);
-		return WEXITSTATUS(fiber->cw.rstatus);
+		return (WIFSIGNALED(fiber->cw.rstatus) ? EINTR :
+			WEXITSTATUS(fiber->cw.rstatus));
 	}
 
 	fiber_set_name(fiber, "dumper");
@@ -312,6 +314,31 @@ signal_free(void)
 		ev_signal_stop(&sigs[i]);
 }
 
+/** Make sure the child has a default signal disposition. */
+static void
+signal_reset()
+{
+	struct sigaction sa;
+
+	/* Reset all signals to their defaults. */
+	memset(&sa, 0, sizeof(sa));
+	sigemptyset(&sa.sa_mask);
+	sa.sa_handler = SIG_DFL;
+
+	if (sigaction(SIGUSR1, &sa, NULL) == -1 ||
+	    sigaction(SIGINT, &sa, NULL) == -1 ||
+	    sigaction(SIGTERM, &sa, NULL) == -1 ||
+	    sigaction(SIGHUP, &sa, NULL) == -1)
+		say_syserror("sigaction");
+
+	/* Unblock any signals blocked by libev. */
+	sigset_t sigset;
+	sigfillset(&sigset);
+	if (sigprocmask(SIG_UNBLOCK, &sigset, NULL) == -1)
+		say_syserror("sigprocmask");
+}
+
+
 /**
  * Adjust the process signal mask and add handlers for signals.
  */
@@ -341,6 +368,7 @@ signal_init(void)
 	ev_signal_start(&sigs[3]);
 
 	atexit(signal_free);
+	tt_pthread_atfork(NULL, NULL, signal_reset);
 }
 
 static void
-- 
GitLab