Commit c56e2b1b authored by Rusty Russell's avatar Rusty Russell

tdb2: fix leak in tests.

parent 04cf551d
...@@ -187,3 +187,10 @@ const char *operation_name(enum operation op) ...@@ -187,3 +187,10 @@ const char *operation_name(enum operation op)
} }
return "**INVALID**"; return "**INVALID**";
} }
void free_external_agent(struct agent *agent)
{
close(agent->cmdfd);
close(agent->responsefd);
free(agent);
}
...@@ -37,4 +37,5 @@ enum agent_return external_agent_operation(struct agent *handle, ...@@ -37,4 +37,5 @@ enum agent_return external_agent_operation(struct agent *handle,
const char *agent_return_name(enum agent_return ret); const char *agent_return_name(enum agent_return ret);
const char *operation_name(enum operation op); const char *operation_name(enum operation op);
void free_external_agent(struct agent *agent);
#endif /* TDB2_TEST_EXTERNAL_AGENT_H */ #endif /* TDB2_TEST_EXTERNAL_AGENT_H */
...@@ -320,3 +320,17 @@ struct tdb_context *tdb_layout_get(struct tdb_layout *layout) ...@@ -320,3 +320,17 @@ struct tdb_context *tdb_layout_get(struct tdb_layout *layout)
return tdb; 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);
}
...@@ -16,6 +16,7 @@ void tdb_layout_add_hashtable(struct tdb_layout *layout, ...@@ -16,6 +16,7 @@ void tdb_layout_add_hashtable(struct tdb_layout *layout,
tdb_len_t extra); tdb_len_t extra);
#endif #endif
struct tdb_context *tdb_layout_get(struct tdb_layout *layout); struct tdb_context *tdb_layout_get(struct tdb_layout *layout);
void tdb_layout_free(struct tdb_layout *layout);
enum layout_type { enum layout_type {
FREETABLE, FREE, DATA, HASHTABLE, FREETABLE, FREE, DATA, HASHTABLE,
......
...@@ -54,6 +54,7 @@ int main(int argc, char *argv[]) ...@@ -54,6 +54,7 @@ int main(int argc, char *argv[])
ok1(free_record_length(tdb, layout->elem[1].base.off) == len); ok1(free_record_length(tdb, layout->elem[1].base.off) == len);
ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0);
tdb_close(tdb); tdb_close(tdb);
tdb_layout_free(layout);
/* No coalescing can be done due to used record */ /* No coalescing can be done due to used record */
layout = new_tdb_layout(NULL); layout = new_tdb_layout(NULL);
...@@ -73,6 +74,7 @@ int main(int argc, char *argv[]) ...@@ -73,6 +74,7 @@ int main(int argc, char *argv[])
ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024); ok1(free_record_length(tdb, layout->elem[1].base.off) == 1024);
ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0);
tdb_close(tdb); tdb_close(tdb);
tdb_layout_free(layout);
/* Coalescing can be done due to two free records, then EOF */ /* Coalescing can be done due to two free records, then EOF */
layout = new_tdb_layout(NULL); layout = new_tdb_layout(NULL);
...@@ -94,6 +96,7 @@ int main(int argc, char *argv[]) ...@@ -94,6 +96,7 @@ int main(int argc, char *argv[])
== 1024 + sizeof(struct tdb_used_record) + 2048); == 1024 + sizeof(struct tdb_used_record) + 2048);
ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0);
tdb_close(tdb); tdb_close(tdb);
tdb_layout_free(layout);
/* Coalescing can be done due to two free records, then data */ /* Coalescing can be done due to two free records, then data */
layout = new_tdb_layout(NULL); layout = new_tdb_layout(NULL);
...@@ -116,6 +119,7 @@ int main(int argc, char *argv[]) ...@@ -116,6 +119,7 @@ int main(int argc, char *argv[])
== 1024 + sizeof(struct tdb_used_record) + 512); == 1024 + sizeof(struct tdb_used_record) + 512);
ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0);
tdb_close(tdb); tdb_close(tdb);
tdb_layout_free(layout);
/* Coalescing can be done due to three free records, then EOF */ /* Coalescing can be done due to three free records, then EOF */
layout = new_tdb_layout(NULL); layout = new_tdb_layout(NULL);
...@@ -140,6 +144,7 @@ int main(int argc, char *argv[]) ...@@ -140,6 +144,7 @@ int main(int argc, char *argv[])
+ sizeof(struct tdb_used_record) + 256); + sizeof(struct tdb_used_record) + 256);
ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0);
tdb_close(tdb); tdb_close(tdb);
tdb_layout_free(layout);
ok1(tap_log_messages == 0); ok1(tap_log_messages == 0);
return exit_status(); return exit_status();
......
...@@ -37,6 +37,7 @@ int main(int argc, char *argv[]) ...@@ -37,6 +37,7 @@ int main(int argc, char *argv[])
/* Fetch should now work. */ /* Fetch should now work. */
d = tdb_fetch(tdb, key); d = tdb_fetch(tdb, key);
ok1(data_equal(d, data)); ok1(data_equal(d, data));
free(d.dptr);
ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0);
tdb_close(tdb); tdb_close(tdb);
} }
......
...@@ -50,8 +50,11 @@ int main(int argc, char *argv[]) ...@@ -50,8 +50,11 @@ int main(int argc, char *argv[])
/* We seemed to lose some keys. /* We seemed to lose some keys.
* Insert and check they're in there! */ * Insert and check they're in there! */
for (j = 0; j < 500; j++) { for (j = 0; j < 500; j++) {
struct tdb_data d;
ok1(tdb_store(tdb, key, data, TDB_REPLACE) == 0); 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); tdb_close(tdb);
} }
......
...@@ -26,13 +26,17 @@ static bool store_records(struct tdb_context *tdb) ...@@ -26,13 +26,17 @@ static bool store_records(struct tdb_context *tdb)
{ {
int i; int i;
struct tdb_data key = { (unsigned char *)&i, sizeof(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++) { for (i = 0; i < 1000; i++) {
if (tdb_store(tdb, key, data, TDB_REPLACE) != 0) if (tdb_store(tdb, key, data, TDB_REPLACE) != 0)
return false; return false;
if (tdb_fetch(tdb, key).dsize != data.dsize) d = tdb_fetch(tdb, key);
if (d.dsize != data.dsize)
return false; return false;
if (memcmp(d.dptr, data.dptr, d.dsize) != 0)
return false;
free(d.dptr);
} }
return true; return true;
} }
...@@ -41,7 +45,7 @@ static void test_val(struct tdb_context *tdb, uint64_t val) ...@@ -41,7 +45,7 @@ static void test_val(struct tdb_context *tdb, uint64_t val)
{ {
uint64_t v; uint64_t v;
struct tdb_data key = { (unsigned char *)&v, sizeof(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. */ /* Insert an entry, then delete it. */
v = val; v = val;
...@@ -65,9 +69,13 @@ static void test_val(struct tdb_context *tdb, uint64_t val) ...@@ -65,9 +69,13 @@ static void test_val(struct tdb_context *tdb, uint64_t val)
ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0);
/* Can find both? */ /* 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; 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. */ /* Delete second one. */
v = val + 1; v = val + 1;
...@@ -85,7 +93,9 @@ static void test_val(struct tdb_context *tdb, uint64_t val) ...@@ -85,7 +93,9 @@ static void test_val(struct tdb_context *tdb, uint64_t val)
/* Can still find second? */ /* Can still find second? */
v = val + 1; 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. */ /* Now, this will be ideally placed. */
v = val + 2; v = val + 2;
...@@ -97,11 +107,17 @@ static void test_val(struct tdb_context *tdb, uint64_t val) ...@@ -97,11 +107,17 @@ static void test_val(struct tdb_context *tdb, uint64_t val)
ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0); ok1(tdb_store(tdb, key, data, TDB_INSERT) == 0);
/* We can still find them all, right? */ /* 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; 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; 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! */ /* And if we delete val + 1, that val + 2 should not move! */
v = val + 1; v = val + 1;
...@@ -109,9 +125,13 @@ static void test_val(struct tdb_context *tdb, uint64_t val) ...@@ -109,9 +125,13 @@ static void test_val(struct tdb_context *tdb, uint64_t val)
ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0);
v = val; 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; 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. */ /* Delete those two, so we are empty. */
ok1(tdb_delete(tdb, key) == 0); ok1(tdb_delete(tdb, key) == 0);
......
...@@ -126,5 +126,6 @@ int main(int argc, char *argv[]) ...@@ -126,5 +126,6 @@ int main(int argc, char *argv[])
} }
ok1(tap_log_messages == 0); ok1(tap_log_messages == 0);
free(buffer);
return exit_status(); return exit_status();
} }
...@@ -62,6 +62,7 @@ int main(int argc, char *argv[]) ...@@ -62,6 +62,7 @@ int main(int argc, char *argv[])
ok1(d.dsize == sizeof(j)); ok1(d.dsize == sizeof(j));
ok1(d.dptr != NULL); ok1(d.dptr != NULL);
ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0); ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0);
free(d.dptr);
} }
/* Now add a *lot* more. */ /* Now add a *lot* more. */
...@@ -73,6 +74,7 @@ int main(int argc, char *argv[]) ...@@ -73,6 +74,7 @@ int main(int argc, char *argv[])
ok1(d.dsize == sizeof(j)); ok1(d.dsize == sizeof(j));
ok1(d.dptr != NULL); ok1(d.dptr != NULL);
ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0); ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0);
free(d.dptr);
} }
ok1(tdb_check(tdb, NULL, NULL) == 0); ok1(tdb_check(tdb, NULL, NULL) == 0);
...@@ -92,6 +94,7 @@ int main(int argc, char *argv[]) ...@@ -92,6 +94,7 @@ int main(int argc, char *argv[])
ok1(d.dsize == sizeof(j)); ok1(d.dsize == sizeof(j));
ok1(d.dptr != NULL); ok1(d.dptr != NULL);
ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0); ok1(d.dptr && memcmp(d.dptr, &j, d.dsize) == 0);
free(d.dptr);
} }
/* Traverse through them. */ /* Traverse through them. */
......
...@@ -65,6 +65,7 @@ int main(int argc, char *argv[]) ...@@ -65,6 +65,7 @@ int main(int argc, char *argv[])
ok1(off == 0); ok1(off == 0);
tdb_close(tdb); tdb_close(tdb);
tdb_layout_free(layout);
ok1(tap_log_messages == 0); ok1(tap_log_messages == 0);
return exit_status(); return exit_status();
......
...@@ -69,5 +69,6 @@ int main(int argc, char *argv[]) ...@@ -69,5 +69,6 @@ int main(int argc, char *argv[])
} }
ok1(tap_log_messages == 0); ok1(tap_log_messages == 0);
free(buffer);
return exit_status(); return exit_status();
} }
#define _XOPEN_SOURCE 500 #define _XOPEN_SOURCE 500
#include <unistd.h> #include <unistd.h>
#include "lock-tracking.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 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 ssize_t write_check(int fd, const void *buf, size_t count);
static int ftruncate_check(int fd, off_t length); static int ftruncate_check(int fd, off_t length);
...@@ -10,6 +13,51 @@ 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 fcntl fcntl_with_lockcheck
#define ftruncate ftruncate_check #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/tdb.c>
#include <ccan/tdb2/free.c> #include <ccan/tdb2/free.c>
#include <ccan/tdb2/lock.c> #include <ccan/tdb2/lock.c>
...@@ -17,8 +65,13 @@ static int ftruncate_check(int fd, off_t length); ...@@ -17,8 +65,13 @@ static int ftruncate_check(int fd, off_t length);
#include <ccan/tdb2/hash.c> #include <ccan/tdb2/hash.c>
#include <ccan/tdb2/check.c> #include <ccan/tdb2/check.c>
#include <ccan/tdb2/transaction.c> #include <ccan/tdb2/transaction.c>
#include <ccan/tap/tap.h> #undef malloc
#include <stdlib.h> #undef free
#undef write
#undef pwrite
#undef fcntl
#undef ftruncate
#include <stdbool.h> #include <stdbool.h>
#include <stdarg.h> #include <stdarg.h>
#include <err.h> #include <err.h>
...@@ -26,11 +79,6 @@ static int ftruncate_check(int fd, off_t length); ...@@ -26,11 +79,6 @@ static int ftruncate_check(int fd, off_t length);
#include "external-agent.h" #include "external-agent.h"
#include "logging.h" #include "logging.h"
#undef write
#undef pwrite
#undef fcntl
#undef ftruncate
static bool in_transaction; static bool in_transaction;
static int target, current; static int target, current;
static jmp_buf jmpbuf; static jmp_buf jmpbuf;
...@@ -150,6 +198,7 @@ reset: ...@@ -150,6 +198,7 @@ reset:
suppress_lockcheck = false; suppress_lockcheck = false;
target++; target++;
current = 0; current = 0;
free_all();
goto reset; goto reset;
} }
...@@ -217,5 +266,6 @@ int main(int argc, char *argv[]) ...@@ -217,5 +266,6 @@ int main(int argc, char *argv[])
ok1(test_death(ops[i], agent)); ok1(test_death(ops[i], agent));
} }
free_external_agent(agent);
return exit_status(); return exit_status();
} }
...@@ -46,5 +46,7 @@ int main(int argc, char *argv[]) ...@@ -46,5 +46,7 @@ int main(int argc, char *argv[])
tdb_close(tdb); tdb_close(tdb);
} }
ok1(tap_log_messages == 0); ok1(tap_log_messages == 0);
free(data.dptr);
return exit_status(); return exit_status();
} }
...@@ -58,5 +58,6 @@ int main(int argc, char *argv[]) ...@@ -58,5 +58,6 @@ int main(int argc, char *argv[])
/* Now store something! */ /* Now store something! */
ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0); ok1(tdb_store(tdb, d, d, TDB_INSERT) == 0);
ok1(tap_log_messages == 0); ok1(tap_log_messages == 0);
free_external_agent(agent);
return exit_status(); return exit_status();
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment