diff --git a/ccan/README b/ccan/README index e08a994a9..a5fc504de 100644 --- a/ccan/README +++ b/ccan/README @@ -1,3 +1,3 @@ CCAN imported from http://ccodearchive.net. -CCAN version: init-2455-gd3d2242b +CCAN version: init-2456-g9d2d2c49 diff --git a/ccan/ccan/pipecmd/test/run-preserve.c b/ccan/ccan/pipecmd/test/run-preserve.c new file mode 100644 index 000000000..c9e7cd96b --- /dev/null +++ b/ccan/ccan/pipecmd/test/run-preserve.c @@ -0,0 +1,98 @@ +#include +/* Include the C files directly. */ +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + pid_t child; + int fd, oldfd, status; + char buf[5] = "test"; + char template[] = "/tmp/run-preserve.XXXXXX"; + + /* We call ourselves, to test pipe. */ + if (argc == 2) { + if (strcmp(argv[1], "out") == 0) { + if (write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf)) + exit(2); + } else if (strcmp(argv[1], "in") == 0) { + if (read(STDIN_FILENO, buf, sizeof(buf)) != sizeof(buf)) + exit(3); + if (memcmp(buf, "test", sizeof(buf)) != 0) + exit(4); + } else if (strcmp(argv[1], "err") == 0) { + if (write(STDERR_FILENO, buf, sizeof(buf)) != sizeof(buf)) + exit(5); + } else + abort(); + exit(0); + } + + /* This is how many tests you plan to run */ + plan_tests(25); + + /* Preserve stdin test. */ + fd = mkstemp(template); + ok1(write(fd, buf, sizeof(buf)) == sizeof(buf)); + ok1(fd >= 0); + ok1(dup2(fd, STDIN_FILENO) == STDIN_FILENO); + ok1(lseek(STDIN_FILENO, 0, SEEK_SET) == 0); + child = pipecmd(&pipecmd_preserve, NULL, NULL, argv[0], "in", NULL); + if (!ok1(child > 0)) + exit(1); + ok1(waitpid(child, &status, 0) == child); + ok1(WIFEXITED(status)); + ok1(WEXITSTATUS(status) == 0); + + close(STDIN_FILENO); + + /* Preserve stdout test */ + fd = open(template, O_WRONLY|O_TRUNC); + ok1(fd >= 0); + oldfd = dup(STDOUT_FILENO); + /* Can't use OK after this, since we mug stdout */ + if (dup2(fd, STDOUT_FILENO) != STDOUT_FILENO) + exit(1); + child = pipecmd(NULL, &pipecmd_preserve, NULL, argv[0], "out", NULL); + if (child == -1) + exit(1); + /* Restore stdout */ + dup2(oldfd, STDOUT_FILENO); + close(oldfd); + ok1(waitpid(child, &status, 0) == child); + ok1(WIFEXITED(status)); + ok1(WEXITSTATUS(status) == 0); + + fd = open(template, O_RDONLY); + ok1(read(fd, buf, sizeof(buf)) == sizeof(buf)); + ok1(close(fd) == 0); + ok1(memcmp(buf, "test", sizeof(buf)) == 0); + + /* Preserve stderr test. */ + fd = open(template, O_WRONLY|O_TRUNC); + ok1(fd >= 0); + oldfd = dup(STDERR_FILENO); + ok1(dup2(fd, STDERR_FILENO) == STDERR_FILENO); + child = pipecmd(NULL, NULL, &pipecmd_preserve, argv[0], "err", NULL); + if (!ok1(child > 0)) + exit(1); + + /* Restore stderr. */ + ok1(dup2(oldfd, STDERR_FILENO)); + ok1(waitpid(child, &status, 0) == child); + ok1(WIFEXITED(status)); + ok1(WEXITSTATUS(status) == 0); + close(oldfd); + + fd = open(template, O_RDONLY); + ok1(read(fd, buf, sizeof(buf)) == sizeof(buf)); + ok1(close(fd) == 0); + ok1(memcmp(buf, "test", sizeof(buf)) == 0); + unlink(template); + + /* This exits depending on whether all tests passed */ + return exit_status(); +} diff --git a/ccan/ccan/tal/tal.c b/ccan/ccan/tal/tal.c index f6e2ee797..dff0dcfba 100644 --- a/ccan/ccan/tal/tal.c +++ b/ccan/ccan/tal/tal.c @@ -385,6 +385,8 @@ static void del_tree(struct tal_hdr *t, const tal_t *orig, int saved_errno) { struct prop_hdr **prop, *p, *next; + assert(!taken(from_tal_hdr(t))); + /* Already being destroyed? Don't loop. */ if (unlikely(get_destroying_bit(t->parent_child))) return; @@ -710,6 +712,10 @@ bool tal_resize_(tal_t **ctxp, size_t size, size_t count, bool clear) /* Fix up linked list pointers. */ t->list.next->prev = t->list.prev->next = &t->list; + /* Copy take() property. */ + if (taken(from_tal_hdr(old_t))) + take(from_tal_hdr(t)); + /* Fix up child property's parent pointer. */ child = find_property(t, CHILDREN); if (child) { diff --git a/ccan/ccan/tal/tal.h b/ccan/ccan/tal/tal.h index 865a69671..e25dcb929 100644 --- a/ccan/ccan/tal/tal.h +++ b/ccan/ccan/tal/tal.h @@ -106,6 +106,9 @@ void *tal_free(const tal_t *p); * This returns true on success (and may move *@p), or false on failure. * On success, tal_count() of *@p will be @count. * + * Note: if *p is take(), it will still be take() upon return, even if it + * has been moved. + * * Example: * tal_resize(&p, 100); */ diff --git a/ccan/ccan/tal/test/run-take-free-assert.c b/ccan/ccan/tal/test/run-take-free-assert.c new file mode 100644 index 000000000..062a778a0 --- /dev/null +++ b/ccan/ccan/tal/test/run-take-free-assert.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(void) +{ + int status; + char *p; + + plan_tests(4); + + /* Test direct free. */ + switch (fork()) { + case 0: + tal_free(take(tal(NULL, char))); + exit(2); + case -1: + exit(1); + default: + wait(&status); + ok1(WIFSIGNALED(status)); + ok1(WTERMSIG(status) == SIGABRT); + } + + /* Test indirect free. */ + switch (fork()) { + case 0: + p = tal(NULL, char); + take(tal(p, char)); + tal_free(p); + exit(2); + case -1: + exit(1); + default: + wait(&status); + ok1(WIFSIGNALED(status)); + ok1(WTERMSIG(status) == SIGABRT); + } + return exit_status(); +} diff --git a/ccan/ccan/tal/test/run-take.c b/ccan/ccan/tal/test/run-take.c index d93304e20..4a7f0c749 100644 --- a/ccan/ccan/tal/test/run-take.c +++ b/ccan/ccan/tal/test/run-take.c @@ -6,7 +6,7 @@ int main(void) { char *parent, *c; - plan_tests(21); + plan_tests(22); /* We can take NULL. */ ok1(take(NULL) == NULL); @@ -44,6 +44,12 @@ int main(void) tal_free(c); ok1(tal_first(parent) == NULL); + /* tal_resize should return a taken pointer. */ + c = take(tal_arr(parent, char, 5)); + tal_resize(&c, 100); + ok1(taken(c)); + tal_free(c); + tal_free(parent); ok1(!taken_any());