tal: allow notifiers on NULL.
authorRusty Russell <rusty@rustcorp.com.au>
Thu, 23 Aug 2018 02:41:13 +0000 (12:11 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 23 Aug 2018 02:41:13 +0000 (12:11 +0930)
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 <rusty@rustcorp.com.au>
ccan/tal/tal.c
ccan/tal/tal.h
ccan/tal/test/run-notifier.c

index 342cce34f03897b7568ae6080c293d52830660dd..f6e2ee797c3e251dae5033bd928e7a61995b2fe6 100644 (file)
@@ -191,14 +191,14 @@ static void *from_tal_hdr(const struct tal_hdr *hdr)
        return (void *)(hdr + 1);
 }
 
        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);
 }
 
 {
        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 ");
 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
                                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);
                }
        }
                                              (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 *))
 {
 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);
        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)
 {
                       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);
        enum tal_notify_type types;
 
         types = del_notifier_property(t, callback, match_extra_arg, extra_arg);
index 54318e1fa116864ae5d00268b9d6c3144ba86eb3..865a696713c88d9243f64515200b49c7c164e554 100644 (file)
@@ -227,7 +227,7 @@ enum tal_notify_type {
 
 /**
  * tal_add_notifier - add a callback function when this context changes.
 
 /**
  * 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.
  *
  * @types: Bitwise OR of the types the callback is interested in.
  * @callback: the function to call.
  *
index 3820444f86f8245c38ffb9817f8d6cb38de506d1..150f00adae9e2d60c0df655ff2ac105e34c2c85a 100644 (file)
@@ -5,7 +5,7 @@
 static enum tal_notify_type expect;
 static void *expect_info;
 static char *ctx;
 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)
 
 /* 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;
 }
 
        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;
        ok1(notify == expect);
        if (expect_info == &expect_info)
                expect_info = info;
@@ -38,6 +38,17 @@ static void notify2(char *ctx UNNEEDED,
        notified2++;
 }
 
        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)
 {
 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;
 
 {
        char *child, *new_ctx;
 
-       plan_tests(56);
+       plan_tests(65);
 
        ctx = tal(NULL, char);
        ok1(tal_add_notifier(ctx, 511, notify1));
 
        ctx = tal(NULL, char);
        ok1(tal_add_notifier(ctx, 511, notify1));
@@ -119,6 +130,20 @@ int main(void)
        ok1(notified1 == 7);
        ok1(notified2 == 1);
 
        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));
        tal_set_backend(NULL, my_realloc, NULL, NULL);
        ctx = new_ctx = tal(NULL, char);
        ok1(tal_add_notifier(new_ctx, 511, resize_notifier));