diff options
Diffstat (limited to 'ctdb/lib/tevent/tevent_signal.c')
-rw-r--r-- | ctdb/lib/tevent/tevent_signal.c | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/ctdb/lib/tevent/tevent_signal.c b/ctdb/lib/tevent/tevent_signal.c index c505419a2d..56bcef9150 100644 --- a/ctdb/lib/tevent/tevent_signal.c +++ b/ctdb/lib/tevent/tevent_signal.c @@ -208,7 +208,7 @@ struct tevent_signal *tevent_common_add_signal(struct tevent_context *ev, /* the sig_state needs to be on a global context as it can last across multiple event contexts */ if (sig_state == NULL) { - sig_state = talloc_zero(talloc_autofree_context(), struct tevent_sig_state); + sig_state = talloc_zero(NULL, struct tevent_sig_state); if (sig_state == NULL) { return NULL; } @@ -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,7 +344,25 @@ 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; + next = sl->next; + + /* + * 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); + #ifdef SA_SIGINFO if (se->sa_flags & SA_SIGINFO) { uint32_t j; @@ -352,17 +379,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; + } } - if (se->sa_flags & SA_RESETHAND) { +#ifdef 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); - if (se->sa_flags & SA_RESETHAND) { +#ifdef SA_RESETHAND + if (exists && (se->sa_flags & SA_RESETHAND)) { talloc_free(se); } +#endif + talloc_free(exists); } #ifdef SA_SIGINFO |