diff options
author | Volker Lendecke <vl@samba.org> | 2012-01-28 22:18:00 +0100 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2012-02-09 10:15:27 +0100 |
commit | b5436fde5bbe5b849212258088add492ee8fc4ce (patch) | |
tree | 71d0f52eb5552476ffd99a72ff08aa699c82e246 | |
parent | 4328f3ccf37d9a1baadbc55f658902e3b16ff125 (diff) | |
download | samba-b5436fde5bbe5b849212258088add492ee8fc4ce.tar.gz samba-b5436fde5bbe5b849212258088add492ee8fc4ce.tar.bz2 samba-b5436fde5bbe5b849212258088add492ee8fc4ce.zip |
tevent: Fix deleting signal events from within themselves
Signed-off-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r-- | lib/tevent/tevent_signal.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c index fabe72cdc8..248dd35883 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,23 @@ 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; + + /* + * We have to be careful to not touch "se" + * after it was deleted in its handler. Thus + * we allocate a child whose destructor will + * tell by nulling out itself that its parent + * is gone. + */ + 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 +378,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 |