From fa98e4c3b320e53caffa30f5f6ae12aa5e37a9a8 Mon Sep 17 00:00:00 2001
From: Bo Yang <boyang@samba.org>
Date: Tue, 9 Feb 2010 17:02:20 +0800
Subject: [PATCH] s3: signals are processed twice in child.

Signed-off-by: Bo Yang <boyang@samba.org>
(cherry picked from commit 8c8bb51de1ac2baa46ac0736fae12c034288e5d4)
---
 lib/tevent/tevent.c          |    7 +++++++
 lib/tevent/tevent_internal.h |    1 +
 lib/tevent/tevent_signal.c   |   33 ++++++++++++++++++++++++++++-----
 3 files changed, 36 insertions(+), 5 deletions(-)

Index: lib/tevent/tevent.c
===================================================================
--- lib/tevent/tevent.c.orig
+++ lib/tevent/tevent.c
@@ -176,6 +176,13 @@ int tevent_common_context_destructor(str
 		sn = se->next;
 		se->event_ctx = NULL;
 		DLIST_REMOVE(ev->signal_events, se);
+		/*
+		 * This is important, Otherwise signals
+		 * are handled twice in child. eg, SIGHUP.
+		 * one added in parent, and another one in
+		 * the child. -- BoYang
+		 */
+		tevent_cleanup_pending_signal_handlers(se);
 	}
 
 	return 0;
Index: lib/tevent/tevent_internal.h
===================================================================
--- lib/tevent/tevent_internal.h.orig
+++ lib/tevent/tevent_internal.h
@@ -299,6 +299,7 @@ struct tevent_signal *tevent_common_add_
 					       const char *handler_name,
 					       const char *location);
 int tevent_common_check_signal(struct tevent_context *ev);
+void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se);
 
 bool tevent_standard_init(void);
 bool tevent_select_init(void);
Index: lib/tevent/tevent_signal.c
===================================================================
--- lib/tevent/tevent_signal.c.orig
+++ lib/tevent/tevent_signal.c
@@ -133,7 +133,9 @@ static void tevent_common_signal_handler
 
 static int tevent_common_signal_list_destructor(struct tevent_common_signal_list *sl)
 {
-	DLIST_REMOVE(sig_state->sig_handlers[sl->se->signum], sl);
+	if (sig_state->sig_handlers[sl->se->signum]) {
+		DLIST_REMOVE(sig_state->sig_handlers[sl->se->signum], sl);
+	}
 	return 0;
 }
 
@@ -154,12 +156,16 @@ static int tevent_signal_destructor(stru
 
 	if (sig_state->sig_handlers[se->signum] == NULL) {
 		/* restore old handler, if any */
-		sigaction(se->signum, sig_state->oldact[se->signum], NULL);
-		sig_state->oldact[se->signum] = NULL;
+		if (sig_state->oldact[se->signum]) {
+			sigaction(se->signum, sig_state->oldact[se->signum], NULL);
+			sig_state->oldact[se->signum] = NULL;
+		}
 #ifdef SA_SIGINFO
 		if (se->sa_flags & SA_SIGINFO) {
-			talloc_free(sig_state->sig_info[se->signum]);
-			sig_state->sig_info[se->signum] = NULL;
+			if (sig_state->sig_info[se->signum]) {
+				talloc_free(sig_state->sig_info[se->signum]);
+				sig_state->sig_info[se->signum] = NULL;
+			}
 		}
 #endif
 	}
@@ -396,3 +402,20 @@ int tevent_common_check_signal(struct te
 
 	return 1;
 }
+
+void tevent_cleanup_pending_signal_handlers(struct tevent_signal *se)
+{
+	struct tevent_common_signal_list *sl;
+	sl = talloc_get_type(se->additional_data,
+			     struct tevent_common_signal_list);
+
+	tevent_common_signal_list_destructor(sl);
+
+	if (sig_state->sig_handlers[se->signum] == NULL) {
+		if (sig_state->oldact[se->signum]) {
+			sigaction(se->signum, sig_state->oldact[se->signum], NULL);
+			sig_state->oldact[se->signum] = NULL;
+		}
+	}
+	return;
+}
