tevent_common_add_signal: struct tevent_signal *(struct tevent_context *, TALLOC_CTX *, int, int, tevent_signal_handler_t, void *, const char *, const char *)
tevent_common_add_timer: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
tevent_common_add_timer_v2: struct tevent_timer *(struct tevent_context *, TALLOC_CTX *, struct timeval, tevent_timer_handler_t, void *, const char *, const char *)
+tevent_common_check_double_free: void (TALLOC_CTX *, const char *)
tevent_common_check_signal: int (struct tevent_context *)
tevent_common_context_destructor: int (struct tevent_context *)
tevent_common_fd_destructor: int (struct tevent_fd *)
return 0;
}
+void tevent_common_check_double_free(TALLOC_CTX *ptr, const char *reason)
+{
+ void *parent_ptr = talloc_parent(ptr);
+ size_t parent_blocks = talloc_total_blocks(parent_ptr);
+
+ if (parent_ptr != NULL && parent_blocks == 0) {
+ /*
+ * This is an implicit talloc free, as we still have a parent
+ * but it's already being destroyed. Note that
+ * talloc_total_blocks(ptr) also just returns 0 if a
+ * talloc_free(ptr) is still in progress of freeing all
+ * children.
+ */
+ return;
+ }
+
+ tevent_abort(NULL, reason);
+}
+
/*
create a event_context structure for a specific implemementation.
This must be the first events call, and all subsequent calls pass
void tevent_abort(struct tevent_context *ev, const char *reason);
+void tevent_common_check_double_free(TALLOC_CTX *ptr, const char *reason);
+
struct tevent_context {
/* the specific events implementation */
const struct tevent_ops *ops;