From a8722345053b7cd860499aa31fd6bb414c120cc8 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 23 Aug 2018 12:11:13 +0930 Subject: [PATCH] tal: allow notifiers on NULL. A destructor on NULL doesn't make sense, but notifiers (eg. new children) do. We fix up a mistake in run-notifier (comparing ctx with itself) and loose typing in tal.c's tal_add_notifier_ too. Signed-off-by: Rusty Russell --- ccan/tal/tal.c | 10 +++++----- ccan/tal/tal.h | 2 +- ccan/tal/test/run-notifier.c | 33 +++++++++++++++++++++++++++++---- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/ccan/tal/tal.c b/ccan/tal/tal.c index 342cce34..f6e2ee79 100644 --- a/ccan/tal/tal.c +++ b/ccan/tal/tal.c @@ -191,14 +191,14 @@ static void *from_tal_hdr(const struct tal_hdr *hdr) return (void *)(hdr + 1); } -#ifdef TAL_DEBUG -static void *from_tal_hdr_or_null(struct tal_hdr *hdr) +static void *from_tal_hdr_or_null(const struct tal_hdr *hdr) { if (hdr == &null_parent.hdr) return NULL; return from_tal_hdr(hdr); } +#ifdef TAL_DEBUG static struct tal_hdr *debug_tal(struct tal_hdr *tal) { tal_check(from_tal_hdr_or_null(tal), "TAL_DEBUG "); @@ -234,7 +234,7 @@ static void notify(const struct tal_hdr *ctx, else n->u.destroy(from_tal_hdr(ctx)); } else - n->u.notifyfn(from_tal_hdr(ctx), type, + n->u.notifyfn(from_tal_hdr_or_null(ctx), type, (void *)info); } } @@ -528,7 +528,7 @@ bool tal_add_destructor2_(const tal_t *ctx, void (*destroy)(void *me, void *arg) bool tal_add_notifier_(const tal_t *ctx, enum tal_notify_type types, void (*callback)(tal_t *, enum tal_notify_type, void *)) { - tal_t *t = debug_tal(to_tal_hdr(ctx)); + struct tal_hdr *t = debug_tal(to_tal_hdr_or_null(ctx)); struct notifier *n; assert(types); @@ -556,7 +556,7 @@ bool tal_del_notifier_(const tal_t *ctx, void (*callback)(tal_t *, enum tal_notify_type, void *), bool match_extra_arg, void *extra_arg) { - struct tal_hdr *t = debug_tal(to_tal_hdr(ctx)); + struct tal_hdr *t = debug_tal(to_tal_hdr_or_null(ctx)); enum tal_notify_type types; types = del_notifier_property(t, callback, match_extra_arg, extra_arg); diff --git a/ccan/tal/tal.h b/ccan/tal/tal.h index 54318e1f..865a6967 100644 --- a/ccan/tal/tal.h +++ b/ccan/tal/tal.h @@ -227,7 +227,7 @@ enum tal_notify_type { /** * tal_add_notifier - add a callback function when this context changes. - * @ptr: The tal allocated object. + * @ptr: The tal allocated object, or NULL. * @types: Bitwise OR of the types the callback is interested in. * @callback: the function to call. * diff --git a/ccan/tal/test/run-notifier.c b/ccan/tal/test/run-notifier.c index 3820444f..150f00ad 100644 --- a/ccan/tal/test/run-notifier.c +++ b/ccan/tal/test/run-notifier.c @@ -5,7 +5,7 @@ static enum tal_notify_type expect; static void *expect_info; static char *ctx; -static unsigned int notified1, notified2; +static unsigned int notified1, notified2, notified_null; /* Make sure we always move on resize. */ static void *my_realloc(void *old, size_t size) @@ -20,9 +20,9 @@ static void *my_realloc(void *old, size_t size) return new; } -static void notify1(char *p UNNEEDED, enum tal_notify_type notify, void *info) +static void notify1(char *p, enum tal_notify_type notify, void *info) { - ok1(ctx == ctx); + ok1(p == ctx); ok1(notify == expect); if (expect_info == &expect_info) expect_info = info; @@ -38,6 +38,17 @@ static void notify2(char *ctx UNNEEDED, notified2++; } +static void notify_null(void *p, enum tal_notify_type notify, void *info) +{ + ok1(p == NULL); + ok1(notify == expect); + if (expect_info == &expect_info) + expect_info = info; + else + ok1(info == expect_info); + notified_null++; +} + static bool seen_move, seen_resize; static void resize_notifier(char *p, enum tal_notify_type notify, void *info) { @@ -62,7 +73,7 @@ int main(void) { char *child, *new_ctx; - plan_tests(56); + plan_tests(65); ctx = tal(NULL, char); ok1(tal_add_notifier(ctx, 511, notify1)); @@ -119,6 +130,20 @@ int main(void) ok1(notified1 == 7); ok1(notified2 == 1); + /* Notifiers on NULL work, too. */ + ok1(tal_add_notifier(NULL, TAL_NOTIFY_ADD_CHILD|TAL_NOTIFY_DEL_CHILD, + notify_null)); + expect = TAL_NOTIFY_ADD_CHILD; + expect_info = &expect_info; + child = tal(NULL, char); + ok1(notified_null == 1); + + expect = TAL_NOTIFY_DEL_CHILD; + expect_info = child; + tal_free(child); + ok1(notified_null == 2); + ok1(tal_del_notifier(NULL, notify_null)); + tal_set_backend(NULL, my_realloc, NULL, NULL); ctx = new_ctx = tal(NULL, char); ok1(tal_add_notifier(new_ctx, 511, resize_notifier)); -- 2.39.2