diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2012-11-19 12:52:41 +1030 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2012-11-19 12:52:41 +1030 |
commit | 34c2962d00c4ec24f248bddfd42f2e79cc6b61ef (patch) | |
tree | c7dd4af3e135e486fd489f95d59d3e25e81848bb | |
parent | 78ba5de2dc4c74f772b9e40cd673476dac6d7a1a (diff) |
tal: make sure tal_free() preserves errno.
Always good form to have cleanup functions preserve errno.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | ccan/tal/tal.c | 3 | ||||
-rw-r--r-- | ccan/tal/tal.h | 2 | ||||
-rw-r--r-- | ccan/tal/test/run-free.c | 25 |
3 files changed, 30 insertions, 0 deletions
diff --git a/ccan/tal/tal.c b/ccan/tal/tal.c index 474c0ff0..f33a069a 100644 --- a/ccan/tal/tal.c +++ b/ccan/tal/tal.c @@ -9,6 +9,7 @@ #include <stddef.h> #include <string.h> #include <limits.h> +#include <errno.h> //#define TAL_DEBUG 1 @@ -482,6 +483,7 @@ static struct tal_hdr *remove_node(struct tal_hdr *t) void tal_free(const tal_t *ctx) { struct tal_hdr *t; + int saved_errno = errno; if (!ctx) return; @@ -489,6 +491,7 @@ void tal_free(const tal_t *ctx) t = debug_tal(to_tal_hdr(ctx)); remove_node(t); del_tree(t); + errno = saved_errno; } void *tal_steal_(const tal_t *new_parent, const tal_t *ctx) diff --git a/ccan/tal/tal.h b/ccan/tal/tal.h index da448d8f..a12e0dc4 100644 --- a/ccan/tal/tal.h +++ b/ccan/tal/tal.h @@ -58,6 +58,8 @@ typedef void tal_t; * * This calls the destructors for p (if any), then does the same for all its * children (recursively) before finally freeing the memory. + * + * Note: errno is preserved by this call. */ void tal_free(const tal_t *p); diff --git a/ccan/tal/test/run-free.c b/ccan/tal/test/run-free.c new file mode 100644 index 00000000..7b9a086e --- /dev/null +++ b/ccan/tal/test/run-free.c @@ -0,0 +1,25 @@ +#include <ccan/tal/tal.h> +#include <ccan/tal/tal.c> +#include <ccan/tap/tap.h> + +static void destroy_errno(char *p) +{ + errno = ENOENT; +} + +int main(void) +{ + char *p; + + plan_tests(2); + + p = tal(NULL, char); + ok1(tal_add_destructor(p, destroy_errno)); + + /* Errno save/restored across free. */ + errno = EINVAL; + tal_free(p); + ok1(errno == EINVAL); + + return exit_status(); +} |