service: Fix refcount leak on ipconfigs
authorDaniel Wagner <daniel.wagner@bmw-carit.de>
Mon, 19 Mar 2012 12:50:41 +0000 (13:50 +0100)
committerPatrik Flykt <patrik.flykt@linux.intel.com>
Tue, 20 Mar 2012 10:03:48 +0000 (12:03 +0200)
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.

src/service.c

index 529a1a0..ba35dc9 100644 (file)
@@ -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);
 }