summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Wagner <daniel.wagner@bmw-carit.de>2012-03-19 13:50:41 +0100
committerPatrik Flykt <patrik.flykt@linux.intel.com>2012-03-20 12:03:48 +0200
commiteb4a4ea46c7707f061d734b5f0ceb4ca7465fa47 (patch)
tree68727502cb30b84d30c51dbb985722568f4f80cf
parent4ce90440a70abce7de5377776e942ff14e7152f9 (diff)
downloadconnman-eb4a4ea46c7707f061d734b5f0ceb4ca7465fa47.tar.gz
connman-eb4a4ea46c7707f061d734b5f0ceb4ca7465fa47.tar.bz2
connman-eb4a4ea46c7707f061d734b5f0ceb4ca7465fa47.zip
service: Fix refcount leak on ipconfigs
In __connman_service_connect() we call __connman_ipconfig_enable() which takes a ref on the ipconfig object. Later when the service state machine is updated service takes another ref. When the device disapears during operation (the user didn't call Service.Disconnect()), we do not call __connman_ipconfig_disable() anymore which would drop one ref.
-rw-r--r--src/service.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/service.c b/src/service.c
index 529a1a07..ba35dc95 100644
--- a/src/service.c
+++ b/src/service.c
@@ -740,6 +740,25 @@ static connman_bool_t is_connected_state(const struct connman_service *service,
return FALSE;
}
+static connman_bool_t is_idle_state(const struct connman_service *service,
+ enum connman_service_state state)
+{
+ switch (state) {
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ case CONNMAN_SERVICE_STATE_DISCONNECT:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ break;
+ case CONNMAN_SERVICE_STATE_IDLE:
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static connman_bool_t is_connecting(struct connman_service *service)
{
return is_connecting_state(service, service->state);
@@ -4946,6 +4965,12 @@ static void service_lower_down(struct connman_ipconfig *ipconfig)
DBG("%s lower down", __connman_ipconfig_get_ifname(ipconfig));
+ if (is_idle_state(service, service->state_ipv4) == FALSE)
+ __connman_ipconfig_disable(service->ipconfig_ipv4);
+
+ if (is_idle_state(service, service->state_ipv6) == FALSE)
+ __connman_ipconfig_disable(service->ipconfig_ipv6);
+
stats_stop(service);
service_save(service);
}