==10868== at 0x109A96: notify (tal.c:220)
==10868== by 0x109F7E: del_tree (tal.c:397)
==10868== by 0x10A31A: tal_free (tal.c:481)
==10868== by 0x10BE73: main (run-destructor.c:75)
==10868== Address 0x4a60bd8 is 8 bytes inside a block of size 32 free'd
==10868== at 0x483BA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10868== by 0x109D4F: del_notifier_property (tal.c:340)
==10868== by 0x10A610: tal_del_notifier_ (tal.c:564)
==10868== by 0x10A687: tal_del_destructor_ (tal.c:576)
==10868== by 0x10B653: remove_own_destructor (run-destructor.c:35)
==10868== by 0x109A67: notify (tal.c:235)
==10868== by 0x109F7E: del_tree (tal.c:397)
==10868== by 0x10A31A: tal_free (tal.c:481)
==10868== by 0x10BE73: main (run-destructor.c:75)
==10868== Block was alloc'd at
==10868== at 0x483A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==10868== by 0x109AD5: allocate (tal.c:245)
==10868== by 0x109C3E: add_notifier_property (tal.c:300)
==10868== by 0x10A467: tal_add_destructor_ (tal.c:516)
==10868== by 0x10BDFE: main (run-destructor.c:74)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
struct notifier {
struct prop_hdr hdr; /* NOTIFIER */
enum tal_notify_type types;
struct notifier {
struct prop_hdr hdr; /* NOTIFIER */
enum tal_notify_type types;
void (*notifyfn)(tal_t *, enum tal_notify_type, void *);
void (*destroy)(tal_t *); /* If NOTIFY_IS_DESTRUCTOR set */
void (*destroy2)(tal_t *, void *); /* If NOTIFY_EXTRA_ARG */
void (*notifyfn)(tal_t *, enum tal_notify_type, void *);
void (*destroy)(tal_t *); /* If NOTIFY_IS_DESTRUCTOR set */
void (*destroy2)(tal_t *, void *); /* If NOTIFY_EXTRA_ARG */
if (n->types & type) {
errno = saved_errno;
if (n->types & NOTIFY_IS_DESTRUCTOR) {
if (n->types & type) {
errno = saved_errno;
if (n->types & NOTIFY_IS_DESTRUCTOR) {
+ /* Blatt this notifier in case it tries to
+ * tal_del_destructor() from inside */
+ union notifier_cb cb = n->u;
+ /* It's a union, so this NULLs destroy2 too! */
+ n->u.destroy = NULL;
if (n->types & NOTIFY_EXTRA_ARG)
if (n->types & NOTIFY_EXTRA_ARG)
- n->u.destroy2(from_tal_hdr(ctx),
- EXTRA_ARG(n));
+ cb.destroy2(from_tal_hdr(ctx),
+ EXTRA_ARG(n));
- n->u.destroy(from_tal_hdr(ctx));
+ cb.destroy(from_tal_hdr(ctx));
} else
n->u.notifyfn(from_tal_hdr_or_null(ctx), type,
(void *)info);
} else
n->u.notifyfn(from_tal_hdr_or_null(ctx), type,
(void *)info);
* @function: the function to call before it's freed.
*
* If @function has not been successfully added as a destructor, this returns
* @function: the function to call before it's freed.
*
* If @function has not been successfully added as a destructor, this returns
+ * false. Note that if we're inside the destructor call itself, this will
+ * return false.
*/
#define tal_del_destructor(ptr, function) \
tal_del_destructor_((ptr), typesafe_cb(void, void *, (function), (ptr)))
*/
#define tal_del_destructor(ptr, function) \
tal_del_destructor_((ptr), typesafe_cb(void, void *, (function), (ptr)))
* @function: the function to call before it's freed.
*
* If @function has not been successfully added as a destructor, this returns
* @function: the function to call before it's freed.
*
* If @function has not been successfully added as a destructor, this returns
+ * false. Note that if we're inside the destructor call itself, this will
+ * return false.
*/
#define tal_del_destructor(ptr, function) \
tal_del_destructor_((ptr), typesafe_cb(void, void *, (function), (ptr)))
*/
#define tal_del_destructor(ptr, function) \
tal_del_destructor_((ptr), typesafe_cb(void, void *, (function), (ptr)))
+static void remove_own_destructor(char *p)
+{
+ destroy_count++;
+ ok1(!tal_del_destructor(p, remove_own_destructor));
+}
+
int main(void)
{
char *child2;
int main(void)
{
char *child2;
destroy_count = 0;
parent = tal(NULL, char);
destroy_count = 0;
parent = tal(NULL, char);
tal_free(parent);
ok1(destroy_count == 4);
tal_free(parent);
ok1(destroy_count == 4);
+ destroy_count = 0;
+ parent = tal(NULL, char);
+ ok1(tal_add_destructor(parent, remove_own_destructor));
+ tal_free(parent);
+ ok1(destroy_count == 1);
+
tal_cleanup();
return exit_status();
}
tal_cleanup();
return exit_status();
}
list_node_init(&t->list);
}
list_node_init(&t->list);
}
-static bool list_node_initted(const struct list_node *n)
+static inline bool list_node_initted(const struct list_node *n)