service: Don't iterate over changing sequence
authorDaniel Wagner <daniel.wagner@bmw-carit.de>
Thu, 22 Sep 2011 13:45:11 +0000 (15:45 +0200)
committerDaniel Wagner <daniel.wagner@bmw-carit.de>
Thu, 22 Sep 2011 13:45:49 +0000 (15:45 +0200)
__connman_service_disconnect_all() should not iterate over
the service_list directly because the ordering of the
services can change when disconnecting a service (e.g. default
service). The iterator might be invalid after a
__connman_service_disconnect() call.

It's better to iterate over a temporary list.

src/service.c

index a6c764c..ae15470 100644 (file)
@@ -4547,6 +4547,7 @@ int __connman_service_disconnect(struct connman_service *service)
 int __connman_service_disconnect_all(void)
 {
        GSequenceIter *iter;
+       GSList *services = NULL, *list;
 
        DBG("");
 
@@ -4555,15 +4556,23 @@ int __connman_service_disconnect_all(void)
        while (g_sequence_iter_is_end(iter) == FALSE) {
                struct connman_service *service = g_sequence_get(iter);
 
+               services = g_slist_prepend(services, service);
+
+               iter = g_sequence_iter_next(iter);
+       }
+
+       for (list = services; list != NULL; list = list->next) {
+               struct connman_service *service = list->data;
+
                service->ignore = TRUE;
 
                set_reconnect_state(service, FALSE);
 
                __connman_service_disconnect(service);
-
-               iter = g_sequence_iter_next(iter);
        }
 
+       g_slist_free(list);
+
        return 0;
 
 }