diff options
author | Jukka Rissanen <jukka.rissanen@linux.intel.com> | 2014-04-03 12:39:18 +0300 |
---|---|---|
committer | Patrik Flykt <patrik.flykt@linux.intel.com> | 2014-04-03 13:05:59 +0300 |
commit | 85f960078fcb9cfbc7a146a187e1d0353cd2fa8b (patch) | |
tree | d9fa9aea3c3ba2d610f2c6e4aab805276858418b | |
parent | 9080023754638b56b9cae0524639ad3c4a98e2b4 (diff) | |
download | connman-85f960078fcb9cfbc7a146a187e1d0353cd2fa8b.tar.gz |
dhcp: Network hash table fixes
The network_table hash removal function remove_network() cannot
be used because of we might have invalidated the DHCP connection
already and then we would try to do it again when DHCP stops.
So when DHCP is stopped, we now remove the corresponding network
from the hash manually. This way we are able to unref the network
because we have a pointer to it (the pointer was lost in earlier version)
and valgrind does not report possibly lost memory for network struct
anymore.
-rw-r--r-- | src/dhcp.c | 35 |
1 files changed, 20 insertions, 15 deletions
@@ -86,6 +86,7 @@ static void dhcp_invalidate(struct connman_dhcp *dhcp, bool callback) { struct connman_service *service; struct connman_ipconfig *ipconfig; + bool network_removed = false; int i; DBG("dhcp %p callback %u", dhcp, callback); @@ -131,10 +132,17 @@ static void dhcp_invalidate(struct connman_dhcp *dhcp, bool callback) __connman_ipconfig_set_gateway(ipconfig, NULL); __connman_ipconfig_set_prefixlen(ipconfig, 0); - if (dhcp->callback && callback) + if (dhcp->callback && callback) { + g_hash_table_remove(network_table, dhcp->network); + network_removed = true; dhcp->callback(dhcp->network, false, NULL); + } out: + if (!network_removed) + g_hash_table_remove(network_table, dhcp->network); + + connman_network_unref(dhcp->network); dhcp_free(dhcp); } @@ -584,16 +592,6 @@ static int dhcp_release(struct connman_dhcp *dhcp) return 0; } -static void remove_network(gpointer user_data) -{ - struct connman_dhcp *dhcp = user_data; - - DBG("dhcp %p", dhcp); - - dhcp_release(dhcp); - dhcp_invalidate(dhcp, false); -} - int __connman_dhcp_start(struct connman_network *network, dhcp_cb callback) { struct connman_dhcp *dhcp; @@ -616,13 +614,20 @@ int __connman_dhcp_start(struct connman_network *network, dhcp_cb callback) void __connman_dhcp_stop(struct connman_network *network) { - DBG(""); + struct connman_dhcp *dhcp; + + DBG("network_table %p network %p", network_table, network); if (!network_table) return; - if (g_hash_table_remove(network_table, network)) - connman_network_unref(network); + dhcp = g_hash_table_lookup(network_table, network); + g_hash_table_remove(network_table, network); + + if (dhcp) { + dhcp_release(dhcp); + dhcp_invalidate(dhcp, false); + } } int __connman_dhcp_init(void) @@ -630,7 +635,7 @@ int __connman_dhcp_init(void) DBG(""); network_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, - NULL, remove_network); + NULL, NULL); return 0; } |