tevent: add tevent_common_check_double_free() helper function
authorStefan Metzmacher <metze@samba.org>
Tue, 17 Apr 2018 14:33:47 +0000 (16:33 +0200)
committerRalph Boehme <slow@samba.org>
Wed, 11 Jul 2018 21:04:19 +0000 (23:04 +0200)
This will be used to generically support TALLOC_FREE() on
event which are currently running.

It aborts on every explicit talloc_free(), but ignores implicit
cleanup when the talloc parent is about to go.

We'll undo the 0.9.36 ABI change on the 0.9.37 release
at the end of this patchset.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
lib/tevent/ABI/tevent-0.9.36.sigs
lib/tevent/tevent.c
lib/tevent/tevent_internal.h

index 07d6e29fddd4e382d504c0490f55174dff1a55e2..8a9d1a6ba1055af094380a4a950427169d8a9245 100644 (file)
@@ -24,6 +24,7 @@ tevent_common_add_fd: struct tevent_fd *(struct tevent_context *, TALLOC_CTX *,
 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 *)
index 222a3a1a3ddd29cff552bfa55f23e43dea870d82..de0436df37366da4ad1b60224b3b22ea31ca963b 100644 (file)
@@ -429,6 +429,25 @@ static int tevent_common_context_constructor(struct tevent_context *ev)
        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
index b13efedb5d92e08ed72afd1173e386d014fab62a..7e15a59d3fb4df607febbe65389c77256e3e7aaf 100644 (file)
@@ -248,6 +248,8 @@ void tevent_debug(struct tevent_context *ev, enum tevent_debug_level level,
 
 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;