Merge remote-tracking branch 'origin/patches-2.0'

This commit is contained in:
Nick Mathewson 2011-10-19 22:44:33 -04:00
commit 128c8d6c0f
2 changed files with 137 additions and 8 deletions

24
event.c
View File

@ -250,8 +250,10 @@ HT_GENERATE(event_debug_map, event_debug_entry, node, hash_debug_entry,
dent->added = 1; \
} else { \
event_errx(_EVENT_ERR_ABORT, \
"%s: noting an add on a non-setup event %p", \
__func__, (ev)); \
"%s: noting an add on a non-setup event %p" \
" (events: 0x%x, fd: %d, flags: 0x%x)", \
__func__, (ev), (ev)->ev_events, \
(ev)->ev_fd, (ev)->ev_flags); \
} \
EVLOCK_UNLOCK(_event_debug_map_lock, 0); \
} \
@ -268,8 +270,10 @@ HT_GENERATE(event_debug_map, event_debug_entry, node, hash_debug_entry,
dent->added = 0; \
} else { \
event_errx(_EVENT_ERR_ABORT, \
"%s: noting a del on a non-setup event %p", \
__func__, (ev)); \
"%s: noting a del on a non-setup event %p" \
" (events: 0x%x, fd: %d, flags: 0x%x)", \
__func__, (ev), (ev)->ev_events, \
(ev)->ev_fd, (ev)->ev_flags); \
} \
EVLOCK_UNLOCK(_event_debug_map_lock, 0); \
} \
@ -284,8 +288,10 @@ HT_GENERATE(event_debug_map, event_debug_entry, node, hash_debug_entry,
dent = HT_FIND(event_debug_map, &global_debug_map, &find); \
if (!dent) { \
event_errx(_EVENT_ERR_ABORT, \
"%s called on a non-initialized event %p", \
__func__, (ev)); \
"%s called on a non-initialized event %p" \
" (events: 0x%x, fd: %d, flags: 0x%x)", \
__func__, (ev), (ev)->ev_events, \
(ev)->ev_fd, (ev)->ev_flags); \
} \
EVLOCK_UNLOCK(_event_debug_map_lock, 0); \
} \
@ -300,8 +306,10 @@ HT_GENERATE(event_debug_map, event_debug_entry, node, hash_debug_entry,
dent = HT_FIND(event_debug_map, &global_debug_map, &find); \
if (dent && dent->added) { \
event_errx(_EVENT_ERR_ABORT, \
"%s called on an already added event %p", \
__func__, (ev)); \
"%s called on an already added event %p" \
" (events: 0x%x, fd: %d, flags: 0x%x)", \
__func__, (ev), (ev)->ev_events, \
(ev)->ev_fd, (ev)->ev_flags); \
} \
EVLOCK_UNLOCK(_event_debug_map_lock, 0); \
} \

View File

@ -1637,6 +1637,124 @@ gaic_launch(struct event_base *base, struct evdns_base *dns_base)
++pending;
}
/* FIXME: We should move this to regress_main.c if anything else needs it.*/
/* Trivial replacements for malloc/free/realloc to check for memory leaks.
* Not threadsafe. */
static int allocated_chunks = 0;
static void *
cnt_malloc(size_t sz)
{
allocated_chunks += 1;
return malloc(sz);
}
static void *
cnt_realloc(void *old, size_t sz)
{
if (!old)
allocated_chunks += 1;
if (!sz)
allocated_chunks -= 1;
return realloc(old, sz);
}
static void
cnt_free(void *ptr)
{
allocated_chunks -= 1;
return free(ptr);
}
struct testleak_env_t {
struct event_base *base;
struct evdns_base *dns_base;
struct evdns_request *req;
struct generic_dns_callback_result r;
};
static void *
testleak_setup(const struct testcase_t *testcase)
{
struct testleak_env_t *env;
allocated_chunks = 0;
event_set_mem_functions(cnt_malloc, cnt_realloc, cnt_free);
event_enable_debug_mode();
/* not mm_calloc: we don't want to mess with the count. */
env = calloc(1, sizeof(struct testleak_env_t));
env->base = event_base_new();
env->dns_base = evdns_base_new(env->base, 0);
env->req = evdns_base_resolve_ipv4(
env->dns_base, "example.com", DNS_QUERY_NO_SEARCH,
generic_dns_callback, &env->r);
return env;
}
static int
testleak_cleanup(const struct testcase_t *testcase, void *env_)
{
int ok = 0;
struct testleak_env_t *env = env_;
/* FIXME: that's `1' because of event_debug_map_HT_GROW */
tt_int_op(allocated_chunks, ==, 1);
ok = 1;
end:
if (env->dns_base)
evdns_base_free(env->dns_base, 0);
if (env->base)
event_base_free(env->base);
if (env)
free(env);
return ok;
}
static struct testcase_setup_t testleak_funcs = {
testleak_setup, testleak_cleanup
};
static void
test_dbg_leak_cancel(void *env_)
{
/* cancel, loop, free/dns, free/base */
struct testleak_env_t *env = env_;
int send_err_shutdown = 1;
evdns_cancel_request(env->dns_base, env->req);
env->req = 0;
/* `req` is freed in callback, that's why one loop is required. */
event_base_loop(env->base, EVLOOP_NONBLOCK);
/* send_err_shutdown means nothing as soon as our request is
* already canceled */
evdns_base_free(env->dns_base, send_err_shutdown);
env->dns_base = 0;
event_base_free(env->base);
env->base = 0;
}
static void
test_dbg_leak_shutdown(void *env_)
{
/* free/dns, loop, free/base */
struct testleak_env_t *env = env_;
int send_err_shutdown = 1;
/* `req` is freed both with `send_err_shutdown` and without it,
* the only difference is `evdns_callback` call */
env->req = 0;
evdns_base_free(env->dns_base, send_err_shutdown);
env->dns_base = 0;
/* `req` is freed in callback, that's why one loop is required */
event_base_loop(env->base, EVLOOP_NONBLOCK);
event_base_free(env->base);
env->base = 0;
}
static void
test_getaddrinfo_async_cancel_stress(void *ptr)
{
@ -1714,6 +1832,9 @@ struct testcase_t dns_testcases[] = {
{ "getaddrinfo_cancel_stress", test_getaddrinfo_async_cancel_stress,
TT_FORK, NULL, NULL },
{ "leak_shutdown", test_dbg_leak_shutdown, TT_FORK, &testleak_funcs, NULL },
{ "leak_cancel", test_dbg_leak_cancel, TT_FORK, &testleak_funcs, NULL },
END_OF_TESTCASES
};