gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

commit a85848d1c6686713c0c977868eba2d5fe4fa322f
parent 3b1199eb8f4a3319a13d34878a956f16c66a5b19
Author: Matthias Wachs <wachs@net.in.tum.de>
Date:   Mon, 15 Jul 2013 09:22:28 +0000

while running transport: valgrind showed memory leak due to not removed resolution processes
storing pretty printer requests and removing them after timeout


Diffstat:
Msrc/transport/plugin_transport_tcp.c | 84++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/transport/plugin_transport_udp.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 166 insertions(+), 3 deletions(-)

diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c @@ -1564,10 +1564,40 @@ tcp_plugin_disconnect (void *cls, const struct GNUNET_PeerIdentity *target) /** + * Running pretty printers: head + */ +static struct PrettyPrinterContext *ppc_dll_head; + +/** + * Running pretty printers: tail + */ +static struct PrettyPrinterContext *ppc_dll_tail; + +/** * Context for address to string conversion. */ struct PrettyPrinterContext { + /** + * DLL + */ + struct PrettyPrinterContext *next; + + /** + * DLL + */ + struct PrettyPrinterContext *prev; + + /** + * Timeout task + */ + GNUNET_SCHEDULER_TaskIdentifier timeout_task; + + /** + * Resolver handle + */ + struct GNUNET_RESOLVER_RequestHandle *resolver_handle; + /** * Function to call with the result. */ @@ -1595,6 +1625,23 @@ struct PrettyPrinterContext }; +void +ppc_cancel_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct PrettyPrinterContext *ppc = cls; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "PPC %p was not removed!\n", ppc); + ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != ppc->resolver_handle) + { + GNUNET_RESOLVER_request_cancel (ppc->resolver_handle); + ppc->resolver_handle = NULL; + } + + GNUNET_CONTAINER_DLL_remove (ppc_dll_head, ppc_dll_tail, ppc); + GNUNET_free (ppc); +} + + /** * Append our port and forward the result. * @@ -1605,14 +1652,31 @@ static void append_port (void *cls, const char *hostname) { struct PrettyPrinterContext *ppc = cls; + struct PrettyPrinterContext *cur; char *ret; if (hostname == NULL) { ppc->asc (ppc->asc_cls, NULL); + GNUNET_CONTAINER_DLL_remove (ppc_dll_head, ppc_dll_tail, ppc); + GNUNET_SCHEDULER_cancel (ppc->timeout_task); + ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK; + ppc->resolver_handle = NULL; + /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "PPC %p was removed!\n", ppc); */ GNUNET_free (ppc); return; } + for (cur = ppc_dll_head; (NULL != cur); cur = cur->next) + { + if (cur == ppc) + break; + } + if (NULL == cur) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid callback for PPC %p \n", ppc); + return; + } + if (GNUNET_YES == ppc->ipv6) GNUNET_asprintf (&ret, "%s.%u.[%s]:%d", PLUGIN_NAME, ppc->options, hostname, ppc->port); else @@ -1702,7 +1766,12 @@ tcp_plugin_address_pretty_printer (void *cls, const char *type, ppc->asc_cls = asc_cls; ppc->port = port; ppc->options = options; - GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc); + ppc->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(timeout, 2), + &ppc_cancel_task, ppc); + GNUNET_CONTAINER_DLL_insert (ppc_dll_head, ppc_dll_tail, ppc); + /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "PPC %p was created!\n", ppc); */ + ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, + timeout, &append_port, ppc); } @@ -2599,6 +2668,8 @@ libgnunet_plugin_transport_tcp_done (void *cls) struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; struct TCPProbeContext *tcp_probe; + struct PrettyPrinterContext *cur; + struct PrettyPrinterContext *next; if (NULL == plugin) { @@ -2612,6 +2683,17 @@ libgnunet_plugin_transport_tcp_done (void *cls) /* Removing leftover NAT sessions */ GNUNET_CONTAINER_multihashmap_iterate(plugin->nat_wait_conns, &session_disconnect_it, NULL); + next = ppc_dll_head; + for (cur = next; NULL != cur; cur = next) + { + next = cur->next; + GNUNET_CONTAINER_DLL_remove (ppc_dll_head, ppc_dll_tail, cur); + GNUNET_RESOLVER_request_cancel (cur->resolver_handle); + GNUNET_SCHEDULER_cancel (cur->timeout_task); + GNUNET_free (cur); + GNUNET_break (0); + } + if (plugin->service != NULL) GNUNET_SERVICE_stop (plugin->service); else diff --git a/src/transport/plugin_transport_udp.c b/src/transport/plugin_transport_udp.c @@ -64,10 +64,40 @@ #define UDP_MAX_SENDER_ADDRESSES_WITH_DEFRAG 128 /** + * Running pretty printers: head + */ +static struct PrettyPrinterContext *ppc_dll_head; + +/** + * Running pretty printers: tail + */ +static struct PrettyPrinterContext *ppc_dll_tail; + +/** * Closure for 'append_port'. */ struct PrettyPrinterContext { + /** + * DLL + */ + struct PrettyPrinterContext *next; + + /** + * DLL + */ + struct PrettyPrinterContext *prev; + + /** + * Timeout task + */ + GNUNET_SCHEDULER_TaskIdentifier timeout_task; + + /** + * Resolver handle + */ + struct GNUNET_RESOLVER_RequestHandle *resolver_handle; + /** * Function to call with the result. */ @@ -672,6 +702,23 @@ udp_string_to_address (void *cls, const char *addr, uint16_t addrlen, } +void +ppc_cancel_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct PrettyPrinterContext *ppc = cls; + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "PPC %p was not removed!\n", ppc); + ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK; + if (NULL != ppc->resolver_handle) + { + GNUNET_RESOLVER_request_cancel (ppc->resolver_handle); + ppc->resolver_handle = NULL; + } + + GNUNET_CONTAINER_DLL_remove (ppc_dll_head, ppc_dll_tail, ppc); + GNUNET_free (ppc); +} + + /** * Append our port and forward the result. * @@ -682,14 +729,31 @@ static void append_port (void *cls, const char *hostname) { struct PrettyPrinterContext *ppc = cls; + struct PrettyPrinterContext *cur; char *ret; if (hostname == NULL) { ppc->asc (ppc->asc_cls, NULL); + GNUNET_CONTAINER_DLL_remove (ppc_dll_head, ppc_dll_tail, ppc); + GNUNET_SCHEDULER_cancel (ppc->timeout_task); + ppc->timeout_task = GNUNET_SCHEDULER_NO_TASK; + ppc->resolver_handle = NULL; + /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "PPC %p was removed!\n", ppc); */ GNUNET_free (ppc); return; } + for (cur = ppc_dll_head; (NULL != cur); cur = cur->next) + { + if (cur == ppc) + break; + } + if (NULL == cur) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid callback for PPC %p \n", ppc); + return; + } + if (GNUNET_YES == ppc->ipv6) GNUNET_asprintf (&ret, "%s.%u.[%s]:%d", PLUGIN_NAME, ppc->options, hostname, ppc->port); else @@ -698,7 +762,6 @@ append_port (void *cls, const char *hostname) GNUNET_free (ret); } - /** * Convert the transports address to a nice, human-readable * format. @@ -784,7 +847,12 @@ udp_plugin_address_pretty_printer (void *cls, const char *type, ppc->ipv6 = GNUNET_YES; else ppc->ipv6 = GNUNET_NO; - GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc); + ppc->timeout_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(timeout, 2), + &ppc_cancel_task, ppc); + GNUNET_CONTAINER_DLL_insert (ppc_dll_head, ppc_dll_tail, ppc); + /* GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "PPC %p was created!\n", ppc); */ + ppc->resolver_handle = GNUNET_RESOLVER_hostname_get (sb, sbs, !numeric, timeout, &append_port, ppc); + } @@ -3083,6 +3151,8 @@ libgnunet_plugin_transport_udp_done (void *cls) { struct GNUNET_TRANSPORT_PluginFunctions *api = cls; struct Plugin *plugin = api->cls; + struct PrettyPrinterContext *cur; + struct PrettyPrinterContext *next; if (NULL == plugin) { @@ -3169,6 +3239,17 @@ libgnunet_plugin_transport_udp_done (void *cls) GNUNET_CONTAINER_multihashmap_iterate (plugin->sessions, &disconnect_and_free_it, plugin); GNUNET_CONTAINER_multihashmap_destroy (plugin->sessions); + next = ppc_dll_head; + for (cur = next; NULL != cur; cur = next) + { + next = cur->next; + GNUNET_CONTAINER_DLL_remove (ppc_dll_head, ppc_dll_tail, cur); + GNUNET_RESOLVER_request_cancel (cur->resolver_handle); + GNUNET_SCHEDULER_cancel (cur->timeout_task); + GNUNET_free (cur); + GNUNET_break (0); + } + plugin->nat = NULL; GNUNET_free (plugin); GNUNET_free (api);