talloc_stack: report lazy freeing (panic if DEVELOPER).
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 17 Jul 2012 19:27:31 +0000 (04:57 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 17 Jul 2012 19:27:31 +0000 (04:57 +0930)
talloc_stackframe() stacks, so if you forget to free one, the outer
one will free it.  However, it's not a good idea to rely too heavily
on this behaviour: it can lead to delays in the release of memory or
destructors.

I had an elaborate hack to make sure every talloc_stackframe() was
freed in the exact same function it was allocated, however all bugs it
caught were simply lazy freeing, so this patch just checks for that.

This doesn't check for stackframes we don't free up on exit: that would
be nice, but uncovers some uncomfortable (but probably harmless) cases.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
lib/util/talloc_stack.c

index 304ea17d8c44d59906f49b933740adf6b90ac9bf..be332af571b54c84ce3534b5c72fb0a48a4a4efd 100644 (file)
@@ -96,6 +96,17 @@ static int talloc_pop(TALLOC_CTX *frame)
                (struct talloc_stackframe *)SMB_THREAD_GET_TLS(global_ts);
        int i;
 
+       /* Catch lazy frame-freeing. */
+       if (ts->talloc_stack[ts->talloc_stacksize-1] != frame) {
+               DEBUG(0, ("Freed frame %s, expected %s.\n",
+                         talloc_get_name(frame),
+                         talloc_get_name(ts->talloc_stack
+                                         [ts->talloc_stacksize-1])));
+#ifdef DEVELOPER
+               smb_panic("Frame not freed in order.");
+#endif
+       }
+
        for (i=ts->talloc_stacksize-1; i>0; i--) {
                if (frame == ts->talloc_stack[i]) {
                        break;