From c56e2b1b5e51b094d53f4012e226b352a91618f6 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 1 Mar 2011 23:19:20 +1030 Subject: [PATCH] tdb2: fix leak in tests. --- ccan/tdb2/test/external-agent.c | 7 ++ ccan/tdb2/test/external-agent.h | 1 + ccan/tdb2/test/layout.c | 14 ++++ ccan/tdb2/test/layout.h | 1 + ccan/tdb2/test/run-03-coalesce.c | 5 ++ ccan/tdb2/test/run-11-simple-fetch.c | 1 + ccan/tdb2/test/run-12-store.c | 5 +- ccan/tdb2/test/run-13-delete.c | 42 ++++++++---- ccan/tdb2/test/run-15-append.c | 1 + ccan/tdb2/test/run-25-hashoverload.c | 3 + ccan/tdb2/test/run-50-multiple-freelists.c | 1 + ccan/tdb2/test/run-55-transaction.c | 1 + .../tdb2/test/run-57-die-during-transaction.c | 64 +++++++++++++++++-- ccan/tdb2/test/run-record-expand.c | 2 + ccan/tdb2/test/run-remap-in-read_traverse.c | 1 + 15 files changed, 130 insertions(+), 19 deletions(-) diff --git a/ccan/tdb2/test/external-agent.c b/ccan/tdb2/test/external-agent.c index fa5ca8b4..35314802 100644 --- a/ccan/tdb2/test/external-agent.c +++ b/ccan/tdb2/test/external-agent.c @@ -187,3 +187,10 @@ const char *operation_name(enum operation op) } return "**INVALID**"; } + +void free_external_agent(struct agent *agent) +{ + close(agent->cmdfd); + close(agent->responsefd); + free(agent); +} diff --git a/ccan/tdb2/test/external-agent.h b/ccan/tdb2/test/external-agent.h index ad537d5d..b5d6c31e 100644 --- a/ccan/tdb2/test/external-agent.h +++ b/ccan/tdb2/test/external-agent.h @@ -37,4 +37,5 @@ enum agent_return external_agent_operation(struct agent *handle, const char *agent_return_name(enum agent_return ret); const char *operation_name(enum operation op); +void free_external_agent(struct agent *agent); #endif /* TDB2_TEST_EXTERNAL_AGENT_H */ diff --git a/ccan/tdb2/test/layout.c b/ccan/tdb2/test/layout.c index d4f68cbf..ad775c8a 100644 --- a/ccan/tdb2/test/layout.c +++ b/ccan/tdb2/test/layout.c @@ -320,3 +320,17 @@ struct tdb_context *tdb_layout_get(struct tdb_layout *layout) return tdb; } + +void tdb_layout_free(struct tdb_layout *layout) +{ + unsigned int i; + + for (i = 0; i < layout->num_elems; i++) { + if (layout->elem[i].base.type == DATA) { + free(layout->elem[i].used.key.dptr); + free(layout->elem[i].used.data.dptr); + } + } + free(layout->elem); + free(layout); +} diff --git a/ccan/tdb2/test/layout.h b/ccan/tdb2/test/layout.h index 083deb47..6e2e6657 100644 --- a/ccan/tdb2/test/layout.h +++ b/ccan/tdb2/test/layout.h @@ -16,6 +16,7 @@ void tdb_layout_add_hashtable(struct tdb_layout *layout, tdb_len_t extra); #endif struct tdb_context *tdb_layout_get(struct tdb_layout *layout); +void tdb_layout_free(struct tdb_layout *layout); enum layout_type { FREETABLE, FREE, DATA, HASHTABLE, diff --git a/ccan/tdb2/test/run-03-coalesce.c b/ccan/tdb2/test/run-03-coalesce.c index a382ae08..621ed01b 100644 --- a/ccan/tdb2/test/run-03-coalesce.c +++ b/ccan/tdb2/test/run-03-coalesce.c @@ -54,6 +54,7 @@ int main(int argc, char *argv[]) ok1(free_record_length(tdb, layout->elem[1].base.off) == len); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); + tdb_layout_free(layout); /* No coalescing can be done due to used record */ layout = new_tdb_layout(NULL); @@ -73,6 +74,7 @@ int main(int argc, char *argv[]) ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); + tdb_layout_free(layout); /* Coalescing can be done due to two free records, then EOF */ layout = new_tdb_layout(NULL); @@ -94,6 +96,7 @@ int main(int argc, char *argv[]) == 1024 + sizeof(struct tdb_used_record) + 2048); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); + tdb_layout_free(layout); /* Coalescing can be done due to two free records, then data */ layout = new_tdb_layout(NULL); @@ -116,6 +119,7 @@ int main(int argc, char *argv[]) == 1024 + sizeof(struct tdb_used_record) + 512); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); + tdb_layout_free(layout); /* Coalescing can be done due to three free records, then EOF */ layout = new_tdb_layout(NULL); @@ -140,6 +144,7 @@ int main(int argc, char *argv[]) + sizeof(struct tdb_used_record) + 256); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); + tdb_layout_free(layout); ok1(tap_log_messages == 0); return exit_status(); diff --git a/ccan/tdb2/test/run-11-simple-fetch.c b/ccan/tdb2/test/run-11-simple-fetch.c index 7225d88d..3a6ac5d9 100644 --- a/ccan/tdb2/test/run-11-simple-fetch.c +++ b/ccan/tdb2/test/run-11-simple-fetch.c @@ -37,6 +37,7 @@ int main(int argc, char *argv[]) /* Fetch should now work. */ d = tdb_fetch(tdb, key); ok1(data_equal(d, data)); + free(d.dptr); ok1(tdb_check(tdb, NULL, NULL) == 0); tdb_close(tdb); } diff --git a/ccan/tdb2/test/run-12-store.c b/ccan/tdb2/test/run-12-store.c index cf4f4a43..dc32d91c 100644 --- a/ccan/tdb2/test/run-12-store.c +++ b/ccan/tdb2/test/run-12-store.c @@ -50,8 +50,11 @@ int main(int argc, char *argv[]) /* We seemed to lose some keys. * Insert and check they're in there! */ for (j = 0; j < 500; j++) { + struct tdb_data d; ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0); - ok1(equal(tdb_fetch(tdb, key), data)); + d = tdb_fetch(tdb, key); + ok1(equal(d, data)); + free(d.dptr); } tdb_close(tdb); } diff --git a/ccan/tdb2/test/run-13-delete.c b/ccan/tdb2/test/run-13-delete.c index ae01e38b..9cf5962e 100644 --- a/ccan/tdb2/test/run-13-delete.c +++ b/ccan/tdb2/test/run-13-delete.c @@ -26,13 +26,17 @@ static bool store_records(struct tdb_context *tdb) { int i; struct tdb_data key = { (unsigned char *)&i, sizeof(i) }; - struct tdb_data data = { (unsigned char *)&i, sizeof(i) }; + struct tdb_data d, data = { (unsigned char *)&i, sizeof(i) }; for (i = 0; i < 1000; i++) { if (tdb_store(tdb, key, data, TDB_REPLACE) != 0) return false; - if (tdb_fetch(tdb, key).dsize != data.dsize) + d = tdb_fetch(tdb, key); + if (d.dsize != data.dsize) return false; + if (memcmp(d.dptr, data.dptr, d.dsize) != 0) + return false; + free(d.dptr); } return true; } @@ -41,7 +45,7 @@ static void test_val(struct tdb_context *tdb, uint64_t val) { uint64_t v; struct tdb_data key = { (unsigned char *)&v, sizeof(v) }; - struct tdb_data data = { (unsigned char *)&v, sizeof(v) }; + struct tdb_data d, data = { (unsigned char *)&v, sizeof(v) }; /* Insert an entry, then delete it. */ v = val; @@ -65,9 +69,13 @@ static void test_val(struct tdb_context *tdb, uint64_t val) ok1(tdb_check(tdb, NULL, NULL) == 0); /* Can find both? */ - ok1(tdb_fetch(tdb, key).dsize == data.dsize); + d = tdb_fetch(tdb, key); + ok1(d.dsize == data.dsize); + free(d.dptr); v = val; - ok1(tdb_fetch(tdb, key).dsize == data.dsize); + d = tdb_fetch(tdb, key); + ok1(d.dsize == data.dsize); + free(d.dptr); /* Delete second one. */ v = val + 1; @@ -85,7 +93,9 @@ static void test_val(struct tdb_context *tdb, uint64_t val) /* Can still find second? */ v = val + 1; - ok1(tdb_fetch(tdb, key).dsize == data.dsize); + d = tdb_fetch(tdb, key); + ok1(d.dsize == data.dsize); + free(d.dptr); /* Now, this will be ideally placed. */ v = val + 2; @@ -97,11 +107,17 @@ static void test_val(struct tdb_context *tdb, uint64_t val) ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); /* We can still find them all, right? */ - ok1(tdb_fetch(tdb, key).dsize == data.dsize); + d = tdb_fetch(tdb, key); + ok1(d.dsize == data.dsize); + free(d.dptr); v = val + 1; - ok1(tdb_fetch(tdb, key).dsize == data.dsize); + d = tdb_fetch(tdb, key); + ok1(d.dsize == data.dsize); + free(d.dptr); v = val + 2; - ok1(tdb_fetch(tdb, key).dsize == data.dsize); + d = tdb_fetch(tdb, key); + ok1(d.dsize == data.dsize); + free(d.dptr); /* And if we delete val + 1, that val + 2 should not move! */ v = val + 1; @@ -109,9 +125,13 @@ static void test_val(struct tdb_context *tdb, uint64_t val) ok1(tdb_check(tdb, NULL, NULL) == 0); v = val; - ok1(tdb_fetch(tdb, key).dsize == data.dsize); + d = tdb_fetch(tdb, key); + ok1(d.dsize == data.dsize); + free(d.dptr); v = val + 2; - ok1(tdb_fetch(tdb, key).dsize == data.dsize); + d = tdb_fetch(tdb, key); + ok1(d.dsize == data.dsize); + free(d.dptr); /* Delete those two, so we are empty. */ ok1(tdb_delete(tdb, key) == 0); diff --git a/ccan/tdb2/test/run-15-append.c b/ccan/tdb2/test/run-15-append.c index fe7a24e0..545175a4 100644 --- a/ccan/tdb2/test/run-15-append.c +++ b/ccan/tdb2/test/run-15-append.c @@ -126,5 +126,6 @@ int main(int argc, char *argv[]) } ok1(tap_log_messages == 0); + free(buffer); return exit_status(); } diff --git a/ccan/tdb2/test/run-25-hashoverload.c b/ccan/tdb2/test/run-25-hashoverload.c index 68e52114..42d49de7 100644 --- a/ccan/tdb2/test/run-25-hashoverload.c +++ b/ccan/tdb2/test/run-25-hashoverload.c @@ -62,6 +62,7 @@ int main(int argc, char *argv[]) ok1(d.dsize == sizeof(j)); ok1(d.dptr != NULL); ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0); + free(d.dptr); } /* Now add a *lot* more. */ @@ -73,6 +74,7 @@ int main(int argc, char *argv[]) ok1(d.dsize == sizeof(j)); ok1(d.dptr != NULL); ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0); + free(d.dptr); } ok1(tdb_check(tdb, NULL, NULL) == 0); @@ -92,6 +94,7 @@ int main(int argc, char *argv[]) ok1(d.dsize == sizeof(j)); ok1(d.dptr != NULL); ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0); + free(d.dptr); } /* Traverse through them. */ diff --git a/ccan/tdb2/test/run-50-multiple-freelists.c b/ccan/tdb2/test/run-50-multiple-freelists.c index 1e33eb1b..b1a8747e 100644 --- a/ccan/tdb2/test/run-50-multiple-freelists.c +++ b/ccan/tdb2/test/run-50-multiple-freelists.c @@ -65,6 +65,7 @@ int main(int argc, char *argv[]) ok1(off == 0); tdb_close(tdb); + tdb_layout_free(layout); ok1(tap_log_messages == 0); return exit_status(); diff --git a/ccan/tdb2/test/run-55-transaction.c b/ccan/tdb2/test/run-55-transaction.c index 4c0dcabc..fe80a358 100644 --- a/ccan/tdb2/test/run-55-transaction.c +++ b/ccan/tdb2/test/run-55-transaction.c @@ -69,5 +69,6 @@ int main(int argc, char *argv[]) } ok1(tap_log_messages == 0); + free(buffer); return exit_status(); } diff --git a/ccan/tdb2/test/run-57-die-during-transaction.c b/ccan/tdb2/test/run-57-die-during-transaction.c index 4711e50e..793636a9 100644 --- a/ccan/tdb2/test/run-57-die-during-transaction.c +++ b/ccan/tdb2/test/run-57-die-during-transaction.c @@ -1,6 +1,9 @@ #define _XOPEN_SOURCE 500 #include #include "lock-tracking.h" +#include +#include +#include static ssize_t pwrite_check(int fd, const void *buf, size_t count, off_t offset); static ssize_t write_check(int fd, const void *buf, size_t count); static int ftruncate_check(int fd, off_t length); @@ -10,6 +13,51 @@ static int ftruncate_check(int fd, off_t length); #define fcntl fcntl_with_lockcheck #define ftruncate ftruncate_check +/* There's a malloc inside transaction_setup_recovery, and valgrind complains + * when we longjmp and leak it. */ +#define MAX_ALLOCATIONS 200 +static void *allocated[MAX_ALLOCATIONS]; + +static void *malloc_noleak(size_t len) +{ + unsigned int i; + + for (i = 0; i < MAX_ALLOCATIONS; i++) + if (!allocated[i]) { + allocated[i] = malloc(len); + return allocated[i]; + } + diag("Too many allocations!"); + abort(); +} + +static void free_noleak(void *p) +{ + unsigned int i; + + /* We don't catch realloc, so don't care if we miss one. */ + for (i = 0; i < MAX_ALLOCATIONS; i++) { + if (allocated[i] == p) { + allocated[i] = NULL; + break; + } + } + free(p); +} + +static void free_all(void) +{ + unsigned int i; + + for (i = 0; i < MAX_ALLOCATIONS; i++) { + free(allocated[i]); + allocated[i] = NULL; + } +} + +#define malloc malloc_noleak +#define free free_noleak + #include #include #include @@ -17,8 +65,13 @@ static int ftruncate_check(int fd, off_t length); #include #include #include -#include -#include +#undef malloc +#undef free +#undef write +#undef pwrite +#undef fcntl +#undef ftruncate + #include #include #include @@ -26,11 +79,6 @@ static int ftruncate_check(int fd, off_t length); #include "external-agent.h" #include "logging.h" -#undef write -#undef pwrite -#undef fcntl -#undef ftruncate - static bool in_transaction; static int target, current; static jmp_buf jmpbuf; @@ -150,6 +198,7 @@ reset: suppress_lockcheck = false; target++; current = 0; + free_all(); goto reset; } @@ -217,5 +266,6 @@ int main(int argc, char *argv[]) ok1(test_death(ops[i], agent)); } + free_external_agent(agent); return exit_status(); } diff --git a/ccan/tdb2/test/run-record-expand.c b/ccan/tdb2/test/run-record-expand.c index 27d58ff3..3f008b0a 100644 --- a/ccan/tdb2/test/run-record-expand.c +++ b/ccan/tdb2/test/run-record-expand.c @@ -46,5 +46,7 @@ int main(int argc, char *argv[]) tdb_close(tdb); } ok1(tap_log_messages == 0); + free(data.dptr); + return exit_status(); } diff --git a/ccan/tdb2/test/run-remap-in-read_traverse.c b/ccan/tdb2/test/run-remap-in-read_traverse.c index 8dd1bf83..fbca83da 100644 --- a/ccan/tdb2/test/run-remap-in-read_traverse.c +++ b/ccan/tdb2/test/run-remap-in-read_traverse.c @@ -58,5 +58,6 @@ int main(int argc, char *argv[]) /* Now store something! */ ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0); ok1(tap_log_messages == 0); + free_external_agent(agent); return exit_status(); } -- 2.39.2