[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[Libevent-users] [patch] more testcases
Here are some patches.
0001 fires without following fixes
aff6ba1 Fix request_finished memory leak with debugging turned on.
9b724b2 Fix evsig_dealloc memory leak with debugging turned on.
0002 is just a preparation for 0003
0003 fires with current codebase but, seems, it should not. I'm sorry,
I can't produce a nice fix right now, so I'm just sharing the testcase
at this moment. :)
And the last question: should I send further patches to ML or via
github pull request?
--
WBRBW, Leonid Evdokimov
xmpp:leon@xxxxxxxxxxxx && http://darkk.net.ru
tel:+79816800702 && tel:+79050965222
From 7a616e13a318a0380a0f298a0779c996883cf4d1 Mon Sep 17 00:00:00 2001
From: Leonid Evdokimov <leon@xxxxxxxxxxxx>
Date: Tue, 18 Oct 2011 17:49:40 +0400
Subject: [PATCH 1/3] Test for commit aff6ba1
---
test/regress_dns.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 116 insertions(+), 0 deletions(-)
diff --git a/test/regress_dns.c b/test/regress_dns.c
index 01cb0db..19581ef 100644
--- a/test/regress_dns.c
+++ b/test/regress_dns.c
@@ -1625,6 +1625,119 @@ gaic_launch(struct event_base *base, struct evdns_base *dns_base)
++pending;
}
+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();
+
+ 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)
{
@@ -1702,6 +1815,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
};
--
1.7.5.4
From 79bcd81586f2e1bd0bf8bb7fd11630b9a68c7ebb Mon Sep 17 00:00:00 2001
From: Leonid Evdokimov <leon@xxxxxxxxxxxx>
Date: Wed, 19 Oct 2011 17:44:17 +0400
Subject: [PATCH 2/3] More detailed message in case of libevent self-debugging
failure.
---
event.c | 24 ++++++++++++++++--------
1 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/event.c b/event.c
index 9064f89..cecba2b 100644
--- a/event.c
+++ b/event.c
@@ -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); \
} \
--
1.7.5.4
From db1e7c404be1e83c424b1f2c2d816647f7ff7c4e Mon Sep 17 00:00:00 2001
From: Leonid Evdokimov <leon@xxxxxxxxxxxx>
Date: Wed, 19 Oct 2011 17:46:08 +0400
Subject: [PATCH 3/3] Some failing tests for self-debugging during
event_reinit.
---
test/regress.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/test/regress.c b/test/regress.c
index f22f01f..5342e2a 100644
--- a/test/regress.c
+++ b/test/regress.c
@@ -883,6 +883,54 @@ test_fork(void)
}
static void
+nop_signal_cb(evutil_socket_t fd, short event, void *arg)
+{
+}
+
+static int mainloop_cfg_st = EVENT_BASE_FLAG_NOLOCK;
+static int mainloop_cfg_mt = 0;
+
+static void
+test_fork_dbg(void* ptr)
+{
+ struct basic_test_data* env = ptr;
+ int *mainloop_cfg = env->setup_data;
+ struct event_config* cfg;
+ struct event_base* base;
+ struct event sig_ev;
+ int pid, status, ok = 0;
+
+ event_enable_debug_mode();
+ if (mainloop_cfg) {
+ cfg = event_config_new();
+ tt_ptr_op(cfg, !=, NULL);
+ event_config_set_flag(cfg, *mainloop_cfg);
+ base = event_base_new_with_config(cfg);
+ } else {
+ base = event_base_new();
+ }
+ tt_ptr_op(base, !=, NULL);
+ evsignal_assign(&sig_ev, base, SIGUSR1, nop_signal_cb, NULL);
+ tt_int_op(evsignal_add(&sig_ev, NULL), ==, 0);
+
+ if ((pid = fork()) == 0) {
+ tt_int_op(event_reinit(base), ==, 0);
+ tt_int_op(evsignal_del(&sig_ev), ==, 0);
+ tt_int_op(event_base_dispatch(base), ==, 1);
+ event_base_free(base);
+ exit(76);
+ }
+ sleep(1);
+ tt_int_op(waitpid(pid, &status, 0), !=, -1);
+ tt_int_op(WEXITSTATUS(status), ==, 76);
+
+ ok = 1;
+end:
+ if (!ok)
+ exit(1);
+}
+
+static void
signal_cb_sa(int sig)
{
test_ok = 2;
@@ -2358,6 +2406,9 @@ struct testcase_t main_testcases[] = {
#ifndef _WIN32
LEGACY(fork, TT_ISOLATED),
+ { "fork_dbg", test_fork_dbg, TT_FORK, &basic_setup, NULL },
+ { "fork_dbg_st", test_fork_dbg, TT_FORK, &basic_setup, &mainloop_cfg_st },
+ { "fork_dbg_mt", test_fork_dbg, TT_FORK, &basic_setup, &mainloop_cfg_mt },
#endif
END_OF_TESTCASES
};
--
1.7.5.4