Commit cbabfa8c authored by Rusty Russell's avatar Rusty Russell

take: add labels when CCAN_TAKE_DEBUG set, return in taken_any().

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 0ea6a212
......@@ -53,6 +53,7 @@ int main(int argc, char *argv[])
if (strcmp(argv[1], "depends") == 0) {
printf("ccan/likely\n");
printf("ccan/str\n");
return 0;
}
......
/* CC0 (Public domain) - see LICENSE file for details */
#include <ccan/take/take.h>
#include <ccan/likely/likely.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const void **takenarr;
static const char **labelarr;
static size_t max_taken, num_taken;
static size_t allocfail;
static void (*allocfailfn)(const void *p);
void *take_(const void *p)
void *take_(const void *p, const char *label)
{
/* Overallocate: it's better than risking calloc returning NULL! */
if (unlikely(label && !labelarr))
labelarr = calloc(max_taken+1, sizeof(*labelarr));
if (unlikely(num_taken == max_taken)) {
const void **new;
......@@ -25,9 +31,16 @@ void *take_(const void *p)
return (void *)p;
}
takenarr = new;
/* Once labelarr is set, we maintain it. */
if (labelarr)
labelarr = realloc(labelarr,
sizeof(*labelarr) * (max_taken+1));
max_taken++;
}
if (unlikely(labelarr))
labelarr[num_taken] = label;
takenarr[num_taken++] = p;
return (void *)p;
}
......@@ -68,9 +81,23 @@ bool is_taken(const void *p)
return find_taken(p) > 0;
}
bool taken_any(void)
const char *taken_any(void)
{
return num_taken != 0;
static char pointer_buf[32];
if (num_taken == 0)
return NULL;
/* We're *allowed* to have some with labels, some without. */
if (labelarr) {
size_t i;
for (i = 0; i < num_taken; i++)
if (labelarr[i])
return labelarr[i];
}
sprintf(pointer_buf, "%p", takenarr[0]);
return pointer_buf;
}
void take_cleanup(void)
......@@ -78,6 +105,8 @@ void take_cleanup(void)
max_taken = num_taken = 0;
free(takenarr);
takenarr = NULL;
free(labelarr);
labelarr = NULL;
}
void take_allocfail(void (*fn)(const void *p))
......
......@@ -3,6 +3,13 @@
#define CCAN_TAKE_H
#include "config.h"
#include <stdbool.h>
#include <ccan/str/str.h>
#ifdef CCAN_TAKE_DEBUG
#define TAKE_LABEL(p) __FILE__ ":" stringify(__LINE__) ":" stringify(p)
#else
#define TAKE_LABEL(p) NULL
#endif
/**
* take - record a pointer to be consumed by the function its handed to.
......@@ -12,7 +19,7 @@
* which is extremely useful for chaining functions. It works on
* NULL, for pass-through error handling.
*/
#define take(p) (take_typeof(p) take_((p)))
#define take(p) (take_typeof(p) take_((p), TAKE_LABEL(p)))
/**
* taken - check (and un-take) a pointer was passed with take()
......@@ -60,7 +67,9 @@ bool is_taken(const void *p);
/**
* taken_any - are there any taken pointers?
*
* Mainly useful for debugging take() leaks.
* Mainly useful for debugging take() leaks. With CCAN_TAKE_DEBUG, returns
* the label where the pointer was passed to take(), otherwise returns
* a static char buffer with the pointer value in it. NULL if none are taken.
*
* Example:
* static void cleanup(void)
......@@ -68,7 +77,7 @@ bool is_taken(const void *p);
* assert(!taken_any());
* }
*/
bool taken_any(void);
const char *taken_any(void);
/**
* take_cleanup - remove all taken pointers from list.
......@@ -112,5 +121,5 @@ void take_allocfail(void (*fn)(const void *p));
#define take_typeof(ptr)
#endif
void *take_(const void *p);
void *take_(const void *p, const char *label);
#endif /* CCAN_TAKE_H */
#include <stdlib.h>
#include <stdbool.h>
#define CCAN_TAKE_DEBUG 1
#include <ccan/take/take.h>
#include <ccan/take/take.c>
#include <ccan/tap/tap.h>
int main(void)
{
const char *p = "hi";
plan_tests(14);
/* We can take NULL. */
ok1(take(NULL) == NULL);
ok1(is_taken(NULL));
ok1(strstr(taken_any(), "run-debug.c:16:"));
ok1(taken(NULL)); /* Undoes take() */
ok1(!is_taken(NULL));
ok1(!taken(NULL));
ok1(!taken_any());
/* We can take a real pointer. */
ok1(take(p) == p);
ok1(is_taken(p));
ok1(strends(taken_any(), "run-debug.c:25:p"));
ok1(taken(p)); /* Undoes take() */
ok1(!is_taken(p));
ok1(!taken(p));
ok1(!taken_any());
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