]> git.ozlabs.org Git - ccan/blob - ccan/tal/tal.c
tal: add general notifiers.
[ccan] / ccan / tal / tal.c
1 /* Licensed under BSD-MIT - see LICENSE file for details */
2 #include <ccan/tal/tal.h>
3 #include <ccan/compiler/compiler.h>
4 #include <ccan/list/list.h>
5 #include <ccan/take/take.h>
6 #include <assert.h>
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <stddef.h>
10 #include <string.h>
11 #include <limits.h>
12 #include <errno.h>
13
14 //#define TAL_DEBUG 1
15
16 /* 32-bit type field, first byte 0 in either endianness. */
17 enum prop_type {
18         CHILDREN = 0x00c1d500,
19         DESTRUCTOR = 0x00de5700,
20         NAME = 0x00111100,
21         NOTIFIER = 0x00071f00
22 };
23
24 struct tal_hdr {
25         struct list_node list;
26         struct prop_hdr *prop;
27         struct children *parent_child;
28 };
29
30 struct prop_hdr {
31         enum prop_type type;
32         struct prop_hdr *next;
33 };
34
35 struct children {
36         struct prop_hdr hdr; /* CHILDREN */
37         struct tal_hdr *parent;
38         struct list_head children; /* Head of siblings. */
39 };
40
41 struct destructor {
42         struct prop_hdr hdr; /* DESTRUCTOR */
43         void (*destroy)(void *me);
44 };
45
46 struct name {
47         struct prop_hdr hdr; /* NAME */
48         char name[];
49 };
50
51 struct notifier {
52         struct prop_hdr hdr; /* NOTIFIER */
53         enum tal_notify_type types;
54         void (*notifyfn)(tal_t *, enum tal_notify_type, void *);
55 };
56
57 static struct {
58         struct tal_hdr hdr;
59         struct children c;
60 } null_parent = { { { &null_parent.hdr.list, &null_parent.hdr.list },
61                     &null_parent.c.hdr, NULL },
62                   { { CHILDREN, NULL },
63                     &null_parent.hdr,
64                     { { &null_parent.c.children.n,
65                         &null_parent.c.children.n } }
66                   }
67 };
68
69
70 static void *(*allocfn)(size_t size) = malloc;
71 static void *(*resizefn)(void *, size_t size) = realloc;
72 static void (*freefn)(void *) = free;
73 static void (*errorfn)(const char *msg) = (void *)abort;
74
75 static inline void COLD call_error(const char *msg)
76 {
77         errorfn(msg);
78 }
79
80 static bool get_destroying_bit(struct children *parent_child)
81 {
82         return (size_t)parent_child & 1;
83 }
84
85 static void set_destroying_bit(struct children **parent_child)
86 {
87         *parent_child = (void *)((size_t)*parent_child | 1);
88 }
89
90 static struct children *ignore_destroying_bit(struct children *parent_child)
91 {
92         return (void *)((size_t)parent_child & ~(size_t)1);
93 }
94
95 static bool initialized = false;
96
97 /* This means valgrind can see leaks. */
98 static void tal_cleanup(void)
99 {
100         struct tal_hdr *i;
101
102         while ((i = list_top(&null_parent.c.children, struct tal_hdr, list)))
103                 list_del(&i->list);
104
105         /* Cleanup any taken pointers. */
106         take_cleanup();
107 }
108
109 /* For allocation failures inside ccan/take */
110 static void take_alloc_failed(const void *p)
111 {
112         tal_free(p);
113 }
114
115 /* We carefully start all real properties with a zero byte. */
116 static bool is_literal(const struct prop_hdr *prop)
117 {
118         return ((char *)prop)[0] != 0;
119 }
120
121 #ifndef NDEBUG
122 static const void *bounds_start, *bounds_end;
123
124 static void update_bounds(const void *new, size_t size)
125 {
126         if (unlikely(!bounds_start)) {
127                 bounds_start = new;
128                 bounds_end = (char *)new + size;
129         } else if (new < bounds_start)
130                 bounds_start = new;
131         else if ((char *)new + size > (char *)bounds_end)
132                 bounds_end = (char *)new + size;
133 }
134
135 static bool in_bounds(const void *p)
136 {
137         return !p
138                 || (p >= (void *)&null_parent && p <= (void *)(&null_parent + 1))
139                 || (p >= bounds_start && p <= bounds_end);
140 }
141 #else
142 static void update_bounds(const void *new, size_t size)
143 {
144 }
145
146 static bool in_bounds(const void *p)
147 {
148         return true;
149 }
150 #endif
151
152 static void check_bounds(const void *p)
153 {
154         if (!in_bounds(p))
155                 call_error("Not a valid header");
156 }
157
158 static struct tal_hdr *to_tal_hdr(const void *ctx)
159 {
160         struct tal_hdr *t;
161
162         t = (struct tal_hdr *)((char *)ctx - sizeof(struct tal_hdr));
163         check_bounds(t);
164         check_bounds(ignore_destroying_bit(t->parent_child));
165         check_bounds(t->list.next);
166         check_bounds(t->list.prev);
167         if (t->prop && !is_literal(t->prop))
168                 check_bounds(t->prop);
169         return t;
170 }
171
172 static struct tal_hdr *to_tal_hdr_or_null(const void *ctx)
173 {
174         if (!ctx)
175                 return &null_parent.hdr;
176         return to_tal_hdr(ctx);
177 }
178
179 static void *from_tal_hdr(const struct tal_hdr *hdr)
180 {
181         return (void *)(hdr + 1);
182 }
183
184 #ifdef TAL_DEBUG
185 static void *from_tal_hdr_or_null(struct tal_hdr *hdr)
186 {
187         if (hdr == &null_parent.hdr)
188                 return NULL;
189         return from_tal_hdr(hdr);
190 }
191
192 static struct tal_hdr *debug_tal(struct tal_hdr *tal)
193 {
194         tal_check(from_tal_hdr_or_null(tal), "TAL_DEBUG ");
195         return tal;
196 }
197 #else
198 static struct tal_hdr *debug_tal(struct tal_hdr *tal)
199 {
200         return tal;
201 }
202 #endif
203
204 static void notify(const struct tal_hdr *ctx,
205                    enum tal_notify_type type, const void *info)
206 {
207         const struct prop_hdr *p;
208
209         for (p = ctx->prop; p; p = p->next) {
210                 struct notifier *n;
211
212                 if (is_literal(p))
213                         break;
214                 if (p->type != NOTIFIER)
215                         continue;
216                 n = (struct notifier *)p;
217                 if (n->types & type)
218                         n->notifyfn(from_tal_hdr(ctx), type, (void *)info);
219         }
220 }
221
222 static void *allocate(size_t size)
223 {
224         void *ret;
225
226         /* Don't hand silly sizes to malloc. */
227         if (size >> (CHAR_BIT*sizeof(size) - 1)) {
228                 call_error("allocation size overflow");
229                 return NULL;
230         }
231
232         ret = allocfn(size);
233         if (!ret)
234                 call_error("allocation failed");
235         else
236                 update_bounds(ret, size);
237         return ret;
238 }
239
240 static struct prop_hdr **find_property_ptr(const struct tal_hdr *t,
241                                            enum prop_type type)
242 {
243         struct prop_hdr **p;
244
245         for (p = (struct prop_hdr **)&t->prop; *p; p = &(*p)->next) {
246                 if (is_literal(*p)) {
247                         if (type == NAME)
248                                 return p;
249                         break;
250                 }
251                 if ((*p)->type == type)
252                         return p;
253         }
254         return NULL;
255 }
256
257 static void *find_property(const struct tal_hdr *parent, enum prop_type type)
258 {
259         struct prop_hdr **p = find_property_ptr(parent, type);
260
261         if (p)
262                 return *p;
263         return NULL;
264 }
265
266 static void init_property(struct prop_hdr *hdr,
267                           struct tal_hdr *parent,
268                           enum prop_type type)
269 {
270         hdr->type = type;
271         hdr->next = parent->prop;
272         parent->prop = hdr;
273 }
274
275 static struct destructor *add_destructor_property(struct tal_hdr *t,
276                                                   void (*destroy)(void *))
277 {
278         struct destructor *prop = allocate(sizeof(*prop));
279         if (prop) {
280                 init_property(&prop->hdr, t, DESTRUCTOR);
281                 prop->destroy = destroy;
282         }
283         return prop;
284 }
285
286 static bool del_destructor_property(struct tal_hdr *t,
287                                     void (*destroy)(void *))
288 {
289         struct prop_hdr **p;
290
291         for (p = (struct prop_hdr **)&t->prop; *p; p = &(*p)->next) {
292                 struct destructor *d;
293
294                 if (is_literal(*p))
295                         break;
296                 if ((*p)->type != DESTRUCTOR)
297                         continue;
298                 d = (struct destructor *)*p;
299                 if (d->destroy == destroy) {
300                         *p = (*p)->next;
301                         freefn(d);
302                         return true;
303                 }
304         }
305         return false;
306 }
307
308 static struct notifier *add_notifier_property(struct tal_hdr *t,
309                                               enum tal_notify_type types,
310                                               void (*fn)(void *,
311                                                          enum tal_notify_type,
312                                                          void *))
313 {
314         struct notifier *prop = allocate(sizeof(*prop));
315         if (prop) {
316                 init_property(&prop->hdr, t, NOTIFIER);
317                 prop->types = types;
318                 prop->notifyfn = fn;
319         }
320         return prop;
321 }
322
323 static bool del_notifier_property(struct tal_hdr *t,
324                                   void (*fn)(tal_t *,
325                                              enum tal_notify_type, void *))
326 {
327         struct prop_hdr **p;
328
329         for (p = (struct prop_hdr **)&t->prop; *p; p = &(*p)->next) {
330                 struct notifier *n;
331
332                 if (is_literal(*p))
333                         break;
334                 if ((*p)->type != NOTIFIER)
335                         continue;
336                 n = (struct notifier *)*p;
337                 if (n->notifyfn == fn) {
338                         *p = (*p)->next;
339                         freefn(n);
340                         return true;
341                 }
342         }
343         return false;
344 }
345
346 static struct name *add_name_property(struct tal_hdr *t, const char *name)
347 {
348         struct name *prop;
349
350         prop = allocate(sizeof(*prop) + strlen(name) + 1);
351         if (prop) {
352                 init_property(&prop->hdr, t, NAME);
353                 strcpy(prop->name, name);
354         }
355         return prop;
356 }
357
358 static struct children *add_child_property(struct tal_hdr *parent,
359                                            struct tal_hdr *child)
360 {
361         struct children *prop = allocate(sizeof(*prop));
362         if (prop) {
363                 init_property(&prop->hdr, parent, CHILDREN);
364                 prop->parent = parent;
365                 list_head_init(&prop->children);
366         }
367         return prop;
368 }
369
370 static bool add_child(struct tal_hdr *parent, struct tal_hdr *child)
371 {
372         struct children *children = find_property(parent, CHILDREN);
373
374         if (!children) {
375                 if (unlikely(!initialized)) {
376                         atexit(tal_cleanup);
377                         take_allocfail(take_alloc_failed);
378                         initialized = true;
379                 }
380                 children = add_child_property(parent, child);
381                 if (!children)
382                         return false;
383         }
384         list_add(&children->children, &child->list);
385         child->parent_child = children;
386         return true;
387 }
388
389 static void del_tree(struct tal_hdr *t, const tal_t *orig)
390 {
391         struct prop_hdr **prop, *p, *next;
392
393         /* Already being destroyed?  Don't loop. */
394         if (unlikely(get_destroying_bit(t->parent_child)))
395                 return;
396
397         set_destroying_bit(&t->parent_child);
398
399         /* Carefully call destructors, removing as we go. */
400         while ((prop = find_property_ptr(t, DESTRUCTOR))) {
401                 struct destructor *d = (struct destructor *)*prop;
402                 d->destroy(from_tal_hdr(t));
403                 *prop = d->hdr.next;
404                 freefn(d);
405         }
406
407         /* Call free notifiers. */
408         notify(t, TAL_NOTIFY_FREE, (tal_t *)orig);
409
410         /* Now free children and groups. */
411         prop = find_property_ptr(t, CHILDREN);
412         if (prop) {
413                 struct tal_hdr *i;
414                 struct children *c = (struct children *)*prop;
415
416                 while ((i = list_top(&c->children, struct tal_hdr, list))) {
417                         list_del(&i->list);
418                         del_tree(i, orig);
419                 }
420         }
421
422         /* Finally free our properties. */
423         for (p = t->prop; p && !is_literal(p); p = next) {
424                 next = p->next;
425                 freefn(p);
426         }
427         freefn(t);
428 }
429
430 void *tal_alloc_(const tal_t *ctx, size_t size, bool clear, const char *label)
431 {
432         struct tal_hdr *child, *parent = debug_tal(to_tal_hdr_or_null(ctx));
433
434         child = allocate(sizeof(struct tal_hdr) + size);
435         if (!child)
436                 return NULL;
437         if (clear)
438                 memset(from_tal_hdr(child), 0, size);
439         child->prop = (void *)label;
440         if (!add_child(parent, child)) {
441                 freefn(child);
442                 return NULL;
443         }
444         debug_tal(parent);
445         notify(parent, TAL_NOTIFY_ADD_CHILD, from_tal_hdr(debug_tal(child)));
446         return from_tal_hdr(debug_tal(child));
447 }
448
449 void *tal_free(const tal_t *ctx)
450 {
451         if (ctx) {
452                 struct tal_hdr *t;
453                 int saved_errno = errno;
454                 t = debug_tal(to_tal_hdr(ctx));
455                 notify(ignore_destroying_bit(t->parent_child)->parent,
456                        TAL_NOTIFY_DEL_CHILD, ctx);
457                 list_del(&t->list);
458                 del_tree(t, ctx);
459                 errno = saved_errno;
460         }
461         return NULL;
462 }
463
464 void *tal_steal_(const tal_t *new_parent, const tal_t *ctx)
465 {
466         if (ctx) {
467                 struct tal_hdr *newpar, *t, *old_parent;
468
469                 newpar = debug_tal(to_tal_hdr_or_null(new_parent));
470                 t = debug_tal(to_tal_hdr(ctx));
471
472                 /* Unlink it from old parent. */
473                 list_del(&t->list);
474                 old_parent = ignore_destroying_bit(t->parent_child)->parent;
475
476                 if (unlikely(!add_child(newpar, t))) {
477                         /* We can always add to old parent, becuase it has a
478                          * children property already. */
479                         if (!add_child(old_parent, t))
480                                 abort();
481                         return NULL;
482                 }
483                 debug_tal(newpar);
484                 notify(t, TAL_NOTIFY_STEAL, new_parent);
485         }
486         return (void *)ctx;
487 }
488
489 bool tal_add_destructor_(tal_t *ctx, void (*destroy)(void *me))
490 {
491         tal_t *t = debug_tal(to_tal_hdr(ctx));
492         return add_destructor_property(t, destroy);
493 }
494
495 bool tal_add_notifier_(tal_t *ctx, enum tal_notify_type types,
496                        void (*callback)(tal_t *, enum tal_notify_type, void *))
497 {
498         tal_t *t = debug_tal(to_tal_hdr(ctx));
499         struct notifier *n;
500
501         assert(types);
502         assert((types & ~(TAL_NOTIFY_FREE | TAL_NOTIFY_STEAL | TAL_NOTIFY_MOVE
503                           | TAL_NOTIFY_RESIZE | TAL_NOTIFY_RENAME
504                           | TAL_NOTIFY_ADD_CHILD | TAL_NOTIFY_DEL_CHILD
505                           | TAL_NOTIFY_ADD_NOTIFIER
506                           | TAL_NOTIFY_DEL_NOTIFIER)) == 0);
507
508         /* Don't call notifier about itself: set types after! */
509         n = add_notifier_property(t, 0, callback);
510         if (unlikely(!n))
511                 return false;
512
513         notify(t, TAL_NOTIFY_ADD_NOTIFIER, callback);
514         n->types = types;
515         return true;
516 }
517
518 bool tal_del_notifier_(tal_t *ctx,
519                        void (*callback)(tal_t *, enum tal_notify_type, void *))
520 {
521         struct tal_hdr *t = debug_tal(to_tal_hdr(ctx));
522         bool ret;
523
524         ret = del_notifier_property(t, callback);
525         if (ret)
526                 notify(t, TAL_NOTIFY_DEL_NOTIFIER, callback);
527         return ret;
528 }
529
530 bool tal_del_destructor_(tal_t *ctx, void (*destroy)(void *me))
531 {
532         struct tal_hdr *t = debug_tal(to_tal_hdr(ctx));
533         return del_destructor_property(t, destroy);
534 }
535
536 bool tal_set_name_(tal_t *ctx, const char *name, bool literal)
537 {
538         struct tal_hdr *t = debug_tal(to_tal_hdr(ctx));
539         struct prop_hdr **prop = find_property_ptr(t, NAME);
540
541         /* Get rid of any old name */
542         if (prop) {
543                 struct name *name = (struct name *)*prop;
544                 if (is_literal(&name->hdr))
545                         *prop = NULL;
546                 else {
547                         *prop = name->hdr.next;
548                         freefn(name);
549                 }
550         }
551
552         if (literal && name[0]) {
553                 struct prop_hdr **p;
554
555                 /* Append literal. */
556                 for (p = &t->prop; *p && !is_literal(*p); p = &(*p)->next);
557                 *p = (struct prop_hdr *)name;
558         } else if (!add_name_property(t, name))
559                 return false;
560
561         debug_tal(t);
562         notify(t, TAL_NOTIFY_RENAME, name);
563         return true;
564 }
565
566 const char *tal_name(const tal_t *t)
567 {
568         struct name *n;
569
570         n = find_property(debug_tal(to_tal_hdr(t)), NAME);
571         if (!n)
572                 return NULL;
573
574         if (is_literal(&n->hdr))
575                 return (const char *)n;
576         return n->name;
577 }
578
579 /* Start one past first child: make stopping natural in circ. list. */
580 static struct tal_hdr *first_child(struct tal_hdr *parent)
581 {
582         struct children *child;
583
584         child = find_property(parent, CHILDREN);
585         if (!child)
586                 return NULL;
587
588         return list_top(&child->children, struct tal_hdr, list);
589 }
590
591 tal_t *tal_first(const tal_t *root)
592 {
593         struct tal_hdr *c, *t = debug_tal(to_tal_hdr_or_null(root));
594
595         c = first_child(t);
596         if (!c)
597                 return NULL;
598         return from_tal_hdr(c);
599 }
600
601 tal_t *tal_next(const tal_t *root, const tal_t *prev)
602 {
603         struct tal_hdr *c, *t = debug_tal(to_tal_hdr(prev)), *top;
604
605         /* Children? */
606         c = first_child(t);
607         if (c)
608                 return from_tal_hdr(c);
609
610         top = to_tal_hdr_or_null(root);
611         do {
612                 struct tal_hdr *next;
613                 struct list_node *end;
614
615                 end = &ignore_destroying_bit(t->parent_child)->children.n;
616
617                 next = list_entry(t->list.next, struct tal_hdr, list);
618                 if (&next->list != end)
619                         return from_tal_hdr(next);
620
621                 /* OK, go back to parent. */
622                 t = ignore_destroying_bit(t->parent_child)->parent;
623         } while (t != top);
624
625         return NULL;
626 }
627
628 tal_t *tal_parent(const tal_t *ctx)
629 {
630         struct tal_hdr *t;
631
632         if (!ctx)
633                 return NULL;
634
635         t = debug_tal(to_tal_hdr(ctx));
636         if (ignore_destroying_bit(t->parent_child)->parent == &null_parent.hdr)
637                 return NULL;
638         return from_tal_hdr(ignore_destroying_bit(t->parent_child)->parent);
639 }
640
641 bool tal_resize_(tal_t **ctxp, size_t size)
642 {
643         struct tal_hdr *old_t, *t;
644         struct children *child;
645
646         old_t = debug_tal(to_tal_hdr(*ctxp));
647
648         /* Don't hand silly sizes to realloc. */
649         if (size >> (CHAR_BIT*sizeof(size) - 1)) {
650                 call_error("Reallocation size overflow");
651                 return false;
652         }
653
654         t = resizefn(old_t, size + sizeof(struct tal_hdr));
655         if (!t) {
656                 call_error("Reallocation failure");
657                 return false;
658         }
659
660         /* If it didn't move, we're done! */
661         if (t != old_t) {
662                 update_bounds(t, size + sizeof(struct tal_hdr));
663
664                 /* Fix up linked list pointers. */
665                 if (list_entry(t->list.next, struct tal_hdr, list) != old_t)
666                         t->list.next->prev = t->list.prev->next = &t->list;
667
668                 /* Fix up child property's parent pointer. */
669                 child = find_property(t, CHILDREN);
670                 if (child) {
671                         assert(child->parent == old_t);
672                         child->parent = t;
673                 }
674                 *ctxp = from_tal_hdr(debug_tal(t));
675                 notify(t, TAL_NOTIFY_MOVE, from_tal_hdr(old_t));
676         }
677         notify(t, TAL_NOTIFY_RESIZE, (void *)size);
678
679         return true;
680 }
681
682 char *tal_strdup(const tal_t *ctx, const char *p)
683 {
684         /* We have to let through NULL for take(). */
685         return tal_dup(ctx, char, p, p ? strlen(p) + 1: 1, 0);
686 }
687
688 char *tal_strndup(const tal_t *ctx, const char *p, size_t n)
689 {
690         size_t len;
691         char *ret;
692
693         /* We have to let through NULL for take(). */
694         if (likely(p)) {
695                 len = strlen(p);
696                 if (len > n)
697                         len = n;
698         } else
699                 len = n;
700
701         ret = tal_dup(ctx, char, p, len, 1);
702         if (ret)
703                 ret[len] = '\0';
704         return ret;
705 }
706
707 void *tal_dup_(const tal_t *ctx, const void *p, size_t n, size_t extra,
708                const char *label)
709 {
710         void *ret;
711
712         /* Beware overflow! */
713         if (n + extra < n || n + extra + sizeof(struct tal_hdr) < n) {
714                 call_error("dup size overflow");
715                 if (taken(p))
716                         tal_free(p);
717                 return NULL;
718         }
719
720         if (taken(p)) {
721                 if (unlikely(!p))
722                         return NULL;
723                 if (unlikely(!tal_resize_((void **)&p, n + extra)))
724                         return tal_free(p);
725                 if (unlikely(!tal_steal(ctx, p)))
726                         return tal_free(p);
727                 return (void *)p;
728         }
729         ret = tal_alloc_(ctx, n + extra, false, label);
730         if (ret)
731                 memcpy(ret, p, n);
732         return ret;
733 }
734
735 char *tal_asprintf(const tal_t *ctx, const char *fmt, ...)
736 {
737         va_list ap;
738         char *ret;
739
740         va_start(ap, fmt);
741         ret = tal_vasprintf(ctx, fmt, ap);
742         va_end(ap);
743
744         return ret;
745 }
746
747 char *tal_vasprintf(const tal_t *ctx, const char *fmt, va_list ap)
748 {
749         size_t max;
750         char *buf;
751         int ret;
752
753         if (!fmt && taken(fmt))
754                 return NULL;
755
756         /* A decent guess to start. */
757         max = strlen(fmt) * 2;
758         buf = tal_arr(ctx, char, max);
759         while (buf) {
760                 va_list ap2;
761
762                 va_copy(ap2, ap);
763                 ret = vsnprintf(buf, max, fmt, ap2);
764                 va_end(ap2);
765
766                 if (ret < max)
767                         break;
768                 if (!tal_resize(&buf, max *= 2))
769                         buf = tal_free(buf);
770         }
771         if (taken(fmt))
772                 tal_free(fmt);
773         return buf;
774 }
775
776 void tal_set_backend(void *(*alloc_fn)(size_t size),
777                      void *(*resize_fn)(void *, size_t size),
778                      void (*free_fn)(void *),
779                      void (*error_fn)(const char *msg))
780 {
781         if (alloc_fn)
782                 allocfn = alloc_fn;
783         if (resize_fn)
784                 resizefn = resize_fn;
785         if (free_fn)
786                 freefn = free_fn;
787         if (error_fn)
788                 errorfn = error_fn;
789 }
790
791 #ifdef CCAN_TAL_DEBUG
792 static void dump_node(unsigned int indent, const struct tal_hdr *t)
793 {
794         unsigned int i;
795         const struct prop_hdr *p;
796
797         for (i = 0; i < indent; i++)
798                 printf("  ");
799         printf("%p", t);
800         for (p = t->prop; p; p = p->next) {
801                 struct children *c;
802                 struct destructor *d;
803                 struct name *n;
804                 struct notifier *no;
805                 if (is_literal(p)) {
806                         printf(" \"%s\"", (const char *)p);
807                         break;
808                 }
809                 switch (p->type) {
810                 case CHILDREN:
811                         c = (struct children *)p;
812                         printf(" CHILDREN(%p):parent=%p,children={%p,%p}\n",
813                                p, c->parent,
814                                c->children.n.prev, c->children.n.next);
815                         break;
816                 case DESTRUCTOR:
817                         d = (struct destructor *)p;
818                         printf(" DESTRUCTOR(%p):fn=%p", p, d->destroy);
819                         break;
820                 case NAME:
821                         n = (struct name *)p;
822                         printf(" NAME(%p):%s", p, n->name);
823                         break;
824                 case NOTIFIER:
825                         no = (struct notifier *)p;
826                         printf(" NOTIFIER(%p):fn=%p", p, no->notifyfn);
827                         break;
828                 default:
829                         printf(" **UNKNOWN(%p):%i**", p, p->type);
830                 }
831         }
832         printf("\n");
833 }
834
835 static void tal_dump_(unsigned int level, const struct tal_hdr *t)
836 {
837         struct children *children;
838
839         dump_node(level, t);
840
841         children = find_property(t, CHILDREN);
842         if (children) {
843                 struct tal_hdr *i;
844
845                 list_for_each(&children->children, i, list)
846                         tal_dump_(level + 1, i);
847         }
848 }
849
850 void tal_dump(void)
851 {
852         tal_dump_(0, &null_parent.hdr);
853 }
854 #endif /* CCAN_TAL_DEBUG */
855
856 #ifndef NDEBUG
857 static bool check_err(struct tal_hdr *t, const char *errorstr,
858                       const char *errmsg)
859 {
860         if (errorstr) {
861                 /* Try not to malloc: it may be corrupted. */
862                 char msg[strlen(errorstr) + 20 + strlen(errmsg) + 1];
863                 sprintf(msg, "%s:%p %s", errorstr, from_tal_hdr(t), errmsg);
864                 call_error(msg);
865         }
866         return false;
867 }
868
869 static bool check_node(struct children *parent_child,
870                        struct tal_hdr *t, const char *errorstr)
871 {
872         struct prop_hdr *p;
873         struct name *name = NULL;
874         struct children *children = NULL;
875
876         if (!in_bounds(t))
877                 return check_err(t, errorstr, "invalid pointer");
878
879         if (ignore_destroying_bit(t->parent_child) != parent_child)
880                 return check_err(t, errorstr, "incorrect parent");
881
882         for (p = t->prop; p; p = p->next) {
883                 if (is_literal(p)) {
884                         if (name)
885                                 return check_err(t, errorstr,
886                                                  "has extra literal");
887                         name = (struct name *)p;
888                         break;
889                 }
890                 if (!in_bounds(p))
891                         return check_err(t, errorstr,
892                                          "has bad property pointer");
893
894                 switch (p->type) {
895                 case CHILDREN:
896                         if (children)
897                                 return check_err(t, errorstr,
898                                                  "has two child nodes");
899                         children = (struct children *)p;
900                         break;
901                 case DESTRUCTOR:
902                 case NOTIFIER:
903                         break;
904                 case NAME:
905                         if (name)
906                                 return check_err(t, errorstr,
907                                                  "has two names");
908                         name = (struct name *)p;
909                         break;
910                 default:
911                         return check_err(t, errorstr, "has unknown property");
912                 }
913         }
914         if (children) {
915                 struct tal_hdr *i;
916
917                 if (!list_check(&children->children, errorstr))
918                         return false;
919                 list_for_each(&children->children, i, list) {
920                         if (!check_node(children, i, errorstr))
921                                 return false;
922                 }
923         }
924         return true;
925 }
926
927 bool tal_check(const tal_t *ctx, const char *errorstr)
928 {
929         struct tal_hdr *t = to_tal_hdr_or_null(ctx);
930
931         return check_node(ignore_destroying_bit(t->parent_child), t, errorstr);
932 }
933 #else /* NDEBUG */
934 bool tal_check(const tal_t *ctx, const char *errorstr)
935 {
936         return true;
937 }
938 #endif