When devices are unplugged and plugged again, __connman_notifier_enable
may be called twice, this will lead the inbalance of enabled refcount,
use bool to indicate the enabled/disabled state as alok's suggest

Fixes BMC#13547
---
 src/notifier.c |   24 ++++++++++--------------
 1 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/src/notifier.c b/src/notifier.c
index 37c23a9..a36222f 100644
--- a/src/notifier.c
+++ b/src/notifier.c
@@ -73,8 +73,8 @@ void connman_notifier_unregister(struct connman_notifier 
*notifier)
 
 #define MAX_TECHNOLOGIES 10
 
+static volatile connman_bool_t enabled[MAX_TECHNOLOGIES];
 static volatile int registered[MAX_TECHNOLOGIES];
-static volatile int enabled[MAX_TECHNOLOGIES];
 static volatile int connected[MAX_TECHNOLOGIES];
 
 void __connman_notifier_list_registered(DBusMessageIter *iter, void *user_data)
@@ -105,7 +105,7 @@ void __connman_notifier_list_enabled(DBusMessageIter *iter, 
void *user_data)
                if (type == NULL)
                        continue;
 
-               if (enabled[i] > 0)
+               if (enabled[i] == TRUE)
                        dbus_message_iter_append_basic(iter,
                                                DBUS_TYPE_STRING, &type);
        }
@@ -296,20 +296,16 @@ void __connman_notifier_enable(enum connman_service_type 
type)
                break;
        }
 
-       if (__sync_fetch_and_add(&enabled[type], 1) == 0)
+       if (__sync_bool_compare_and_swap(&enabled[type], FALSE, TRUE))
                technology_enabled(type, TRUE);
+       else
+               DBG("notifier already enabled");
 }
 
 void __connman_notifier_disable(enum connman_service_type type)
 {
        DBG("type %d", type);
 
-       __sync_synchronize();
-       if (enabled[type] == 0) {
-               connman_error("notifier disable underflow");
-               return;
-       }
-
        switch (type) {
        case CONNMAN_SERVICE_TYPE_UNKNOWN:
        case CONNMAN_SERVICE_TYPE_SYSTEM:
@@ -325,10 +321,10 @@ void __connman_notifier_disable(enum connman_service_type 
type)
                break;
        }
 
-       if (__sync_fetch_and_sub(&enabled[type], 1) != 1)
-               return;
-
-       technology_enabled(type, FALSE);
+       if (__sync_bool_compare_and_swap(&enabled[type], TRUE, FALSE))
+               technology_enabled(type, FALSE);
+       else
+               DBG("notifier already disabled");
 }
 
 void __connman_notifier_connect(enum connman_service_type type)
@@ -605,7 +601,7 @@ connman_bool_t __connman_notifier_is_enabled(enum 
connman_service_type type)
                return FALSE;
 
        __sync_synchronize();
-       if (enabled[type] > 0)
+       if (enabled[type] == TRUE)
                return TRUE;
 
        return FALSE;
-- 
1.7.2.2

_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to