tdb2: fix leak in tests.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 1 Mar 2011 12:49:20 +0000 (23:19 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 1 Mar 2011 12:49:20 +0000 (23:19 +1030)
15 files changed:
ccan/tdb2/test/external-agent.c
ccan/tdb2/test/external-agent.h
ccan/tdb2/test/layout.c
ccan/tdb2/test/layout.h
ccan/tdb2/test/run-03-coalesce.c
ccan/tdb2/test/run-11-simple-fetch.c
ccan/tdb2/test/run-12-store.c
ccan/tdb2/test/run-13-delete.c
ccan/tdb2/test/run-15-append.c
ccan/tdb2/test/run-25-hashoverload.c
ccan/tdb2/test/run-50-multiple-freelists.c
ccan/tdb2/test/run-55-transaction.c
ccan/tdb2/test/run-57-die-during-transaction.c
ccan/tdb2/test/run-record-expand.c
ccan/tdb2/test/run-remap-in-read_traverse.c

index fa5ca8b4904a8662c314b901cf7c7c0986928155..353148029736ac635d456077bb0716815c92fc8a 100644 (file)
@@ -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);
+}
index ad537d5d91635777e9ed279068922bf2dd43c51d..b5d6c31e1cfa5a875cc1187d28014d4dd8c7be5e 100644 (file)
@@ -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 */
index d4f68cbf836a6d5f836215cb8e221a39df16bf3d..ad775c8ad49483f4275d1fedb0bc718bd1b6e9b4 100644 (file)
@@ -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);
+}
index 083deb4722568cffe7a192b4773c606f51b12c3b..6e2e6657a70451050db62ee2879657e6e8cb9f8b 100644 (file)
@@ -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,
index a382ae08ddcb9b10a053201ee08f68d119e9bcfd..621ed01bd401679c51e388f88b022def7f3d3ba1 100644 (file)
@@ -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();
index 7225d88d3f583eba758f4e90dfc84f4192bd84d5..3a6ac5d97fc312290720476b76fc6ef7d6098fa9 100644 (file)
@@ -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);
                }
index cf4f4a4361fb88a077d2bd50470c93400bd108c4..dc32d91cde5a6d918527ca8a71fa562878b57cf8 100644 (file)
@@ -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);
        }
index ae01e38bf721c6c5008f0f27807f7c5313255643..9cf5962eca5be9aa257ffdb230340228c0561ba0 100644 (file)
@@ -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);
index fe7a24e0eb402767891a7705d58b9c0a0a2113c8..545175a4885cb5b3e289fd277ea29b69c8007825 100644 (file)
@@ -126,5 +126,6 @@ int main(int argc, char *argv[])
        }
 
        ok1(tap_log_messages == 0);
+       free(buffer);
        return exit_status();
 }
index 68e52114d7b7903ae51329a83aca3b3f6b9f2e8d..42d49de7e88c00e7edc23e3dbdb82fb1894ede6a 100644 (file)
@@ -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. */
index 1e33eb1b0161e9e917768bff19bbb9862d6a708a..b1a8747e590ab795406a7586a67ce8aef7350ea6 100644 (file)
@@ -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();
index 4c0dcabcbc03ef8aa044ddfcd78c23850c5e8141..fe80a358590e521e42884b8eaac2d7ff02b59543 100644 (file)
@@ -69,5 +69,6 @@ int main(int argc, char *argv[])
        }
 
        ok1(tap_log_messages == 0);
+       free(buffer);
        return exit_status();
 }
index 4711e50e4392400f326f77013ecb0885bb408758..793636a9f6e9c0b30d9fbabfd358febb8bb1efb2 100644 (file)
@@ -1,6 +1,9 @@
 #define _XOPEN_SOURCE 500
 #include <unistd.h>
 #include "lock-tracking.h"
+#include <ccan/tap/tap.h>
+#include <stdlib.h>
+#include <assert.h>
 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 <ccan/tdb2/tdb.c>
 #include <ccan/tdb2/free.c>
 #include <ccan/tdb2/lock.c>
@@ -17,8 +65,13 @@ static int ftruncate_check(int fd, off_t length);
 #include <ccan/tdb2/hash.c>
 #include <ccan/tdb2/check.c>
 #include <ccan/tdb2/transaction.c>
-#include <ccan/tap/tap.h>
-#include <stdlib.h>
+#undef malloc
+#undef free
+#undef write
+#undef pwrite
+#undef fcntl
+#undef ftruncate
+
 #include <stdbool.h>
 #include <stdarg.h>
 #include <err.h>
@@ -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();
 }
index 27d58ff36ab4d35cb955f5cec516728031052e68..3f008b0a6f91eabcf300eaa123145e20a1cb467f 100644 (file)
@@ -46,5 +46,7 @@ int main(int argc, char *argv[])
                tdb_close(tdb);
        }
        ok1(tap_log_messages == 0);
+       free(data.dptr);
+
        return exit_status();
 }
index 8dd1bf8330449dc20bc8d12f32c8cf282be6bc15..fbca83da5950f48fe52f2183c1cad6449d4ca07c 100644 (file)
@@ -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();
 }