#include "replace.h"
#include "system/filesys.h"
#include "system/wait.h"
+#define TEVENT_DEPRECATED 1
#include "tevent.h"
#include "tevent_internal.h"
#include "tevent_util.h"
*/
static int tevent_signal_destructor(struct tevent_signal *se)
{
- struct tevent_common_signal_list *sl =
- talloc_get_type_abort(se->additional_data,
- struct tevent_common_signal_list);
+ if (se->destroyed) {
+ tevent_common_check_double_free(se, "tevent_signal double free");
+ goto done;
+ }
+ se->destroyed = true;
- if (se->event_ctx) {
- struct tevent_context *ev = se->event_ctx;
+ TALLOC_FREE(se->additional_data);
- DLIST_REMOVE(ev->signal_events, se);
+ if (se->event_ctx != NULL) {
+ DLIST_REMOVE(se->event_ctx->signal_events, se);
}
- se->additional_data = NULL;
- talloc_free(sl);
-
if (sig_state->sig_handlers[se->signum] == NULL) {
/* restore old handler, if any */
if (sig_state->oldact[se->signum]) {
sigaction(se->signum, sig_state->oldact[se->signum], NULL);
- talloc_free(sig_state->oldact[se->signum]);
- sig_state->oldact[se->signum] = NULL;
+ TALLOC_FREE(sig_state->oldact[se->signum]);
}
#ifdef SA_SIGINFO
if (se->sa_flags & SA_SIGINFO) {
if (sig_state->sig_info[se->signum]) {
- talloc_free(sig_state->sig_info[se->signum]);
- sig_state->sig_info[se->signum] = NULL;
+ TALLOC_FREE(sig_state->sig_info[se->signum]);
}
}
#endif
}
+ se->event_ctx = NULL;
+done:
+ if (se->busy) {
+ return -1;
+ }
+ se->wrapper = NULL;
+
return 0;
}
return se;
}
-struct tevent_se_exists {
- struct tevent_se_exists **myself;
-};
-
-static int tevent_se_exists_destructor(struct tevent_se_exists *s)
+int tevent_common_invoke_signal_handler(struct tevent_signal *se,
+ int signum, int count, void *siginfo,
+ bool *removed)
{
- *s->myself = NULL;
+ struct tevent_context *handler_ev = se->event_ctx;
+ bool remove = false;
+
+ if (removed != NULL) {
+ *removed = false;
+ }
+
+ if (se->event_ctx == NULL) {
+ return 0;
+ }
+
+ se->busy = true;
+ if (se->wrapper != NULL) {
+ handler_ev = se->wrapper->wrap_ev;
+
+ tevent_wrapper_push_use_internal(handler_ev, se->wrapper);
+ se->wrapper->ops->before_signal_handler(
+ se->wrapper->wrap_ev,
+ se->wrapper->private_state,
+ se->wrapper->main_ev,
+ se,
+ signum,
+ count,
+ siginfo,
+ se->handler_name,
+ se->location);
+ }
+ se->handler(handler_ev, se, signum, count, siginfo, se->private_data);
+ if (se->wrapper != NULL) {
+ se->wrapper->ops->after_signal_handler(
+ se->wrapper->wrap_ev,
+ se->wrapper->private_state,
+ se->wrapper->main_ev,
+ se,
+ signum,
+ count,
+ siginfo,
+ se->handler_name,
+ se->location);
+ tevent_wrapper_pop_use_internal(handler_ev, se->wrapper);
+ }
+ se->busy = false;
+
+#ifdef SA_RESETHAND
+ if (se->sa_flags & SA_RESETHAND) {
+ remove = true;
+ }
+#endif
+
+ if (se->destroyed) {
+ talloc_set_destructor(se, NULL);
+ remove = true;
+ }
+
+ if (remove) {
+ TALLOC_FREE(se);
+ if (removed != NULL) {
+ *removed = true;
+ }
+ }
+
return 0;
}
struct tevent_common_signal_list *sl, *next;
struct tevent_sigcounter counter = sig_state->signal_count[i];
uint32_t count = tevent_sig_count(counter);
+ int ret;
#ifdef SA_SIGINFO
/* Ensure we null out any stored siginfo_t entries
* after processing for debugging purposes. */
}
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;
* signals in the ringbuffer. */
uint32_t ofs = (counter.seen + j)
% TEVENT_SA_INFO_QUEUE_COUNT;
- se->handler(ev, se, i, 1,
- (void*)&sig_state->sig_info[i][ofs],
- se->private_data);
- if (!exists) {
+ bool removed = false;
+
+ ret = tevent_common_invoke_signal_handler(
+ se, i, 1,
+ (void*)&sig_state->sig_info[i][ofs],
+ &removed);
+ if (ret != 0) {
+ tevent_abort(ev, "tevent_common_invoke_signal_handler() failed");
+ }
+ if (removed) {
break;
}
}
-#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);
-#ifdef SA_RESETHAND
- if (exists && (se->sa_flags & SA_RESETHAND)) {
- talloc_free(se);
+
+ ret = tevent_common_invoke_signal_handler(se, i, count,
+ NULL, NULL);
+ if (ret != 0) {
+ tevent_abort(ev, "tevent_common_invoke_signal_handler() failed");
}
-#endif
- talloc_free(exists);
}
#ifdef SA_SIGINFO