Problem in tevent_signal

Volker Lendecke Volker.Lendecke at SerNet.DE
Sat Jan 28 14:31:25 MST 2012


On Sat, Jan 28, 2012 at 09:13:00PM +0100, Volker Lendecke wrote:
> Destroying a tevent_signal event from within its handler
> isn't supported right now. See the following code sequence
> from tevent_signal.c:
> 
>         se->handler(ev, se, i, count, NULL, se->private_data);
> #ifdef SA_RESETHAND
>         if (se->sa_flags & SA_RESETHAND) {
>                 talloc_free(se);
>         }
> #endif
> 
> The signal handler might be gone after it was executed.
> 
> The trick used in tevent_timed is probably not really
> appropriate, we might run the same event more than once.
> 
> Working on it, maybe someone else has a bright idea how to
> solve this.

Not the most elegant fix, but it seems to fix the issue for
me. Needs commenting I think. And maybe we should re-use the
object by doing talloc_steal.

Comments?

Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
>From 68326aeb26d936a5d7384135cdf9b9fdcbb09ae6 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Sat, 28 Jan 2012 22:18:00 +0100
Subject: [PATCH] tevent: Fix deleting signal events from within themselves

---
 lib/tevent/tevent_signal.c |   28 ++++++++++++++++++++++++++--
 1 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c
index fabe72c..e642920 100644
--- a/lib/tevent/tevent_signal.c
+++ b/lib/tevent/tevent_signal.c
@@ -307,6 +307,15 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev,
 	return se;
 }
 
+struct tevent_se_exists {
+	struct tevent_se_exists **myself;
+};
+
+static int tevent_se_exists_destructor(struct tevent_se_exists *s)
+{
+	*s->myself = NULL;
+	return 0;
+}
 
 /*
   check if a signal is pending
@@ -335,6 +344,16 @@ int tevent_common_check_signal(struct tevent_context *ev)
 		}
 		for (sl=sig_state->sig_handlers[i];sl;sl=next) {
 			struct tevent_signal *se = sl->se;
+			struct tevent_se_exists *exists;
+
+			exists = talloc(se, struct tevent_se_exists);
+			if (exists == NULL) {
+				continue;
+			}
+			exists->myself = &exists;
+			talloc_set_destructor(
+				exists, tevent_se_exists_destructor);
+
 			next = sl->next;
 #ifdef SA_SIGINFO
 			if (se->sa_flags & SA_SIGINFO) {
@@ -352,21 +371,26 @@ int tevent_common_check_signal(struct tevent_context *ev)
 					se->handler(ev, se, i, 1,
 						    (void*)&sig_state->sig_info[i][ofs], 
 						    se->private_data);
+					if (!exists) {
+						break;
+					}
 				}
 #ifdef SA_RESETHAND
-				if (se->sa_flags & SA_RESETHAND) {
+				if (exists && (se->sa_flags & SA_RESETHAND)) {
 					talloc_free(se);
 				}
 #endif
+				talloc_free(exists);
 				continue;
 			}
 #endif
 			se->handler(ev, se, i, count, NULL, se->private_data);
 #ifdef SA_RESETHAND
-			if (se->sa_flags & SA_RESETHAND) {
+			if (exists && (se->sa_flags & SA_RESETHAND)) {
 				talloc_free(se);
 			}
 #endif
+			talloc_free(exists);
 		}
 
 #ifdef SA_SIGINFO
-- 
1.7.5.4



More information about the samba-technical mailing list