summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Xu <martin.xu@intel.com>2009-07-10 12:29:36 +0800
committerMarcel Holtmann <marcel@holtmann.org>2009-07-09 22:28:18 -0700
commit1ef7930086f2d99bbaa523609fcdb8cc47753356 (patch)
tree5e5f2bc87d79a63a577efd07f40113793f6e2d77
parent50362b15a291893ec4a79168a24c6b2be3e6558a (diff)
downloadconnman-1ef7930086f2d99bbaa523609fcdb8cc47753356.tar.gz
connman-1ef7930086f2d99bbaa523609fcdb8cc47753356.tar.bz2
connman-1ef7930086f2d99bbaa523609fcdb8cc47753356.zip
Fix disconnect race condition issue in WiFi supplicant
-rw-r--r--plugins/supplicant.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/plugins/supplicant.c b/plugins/supplicant.c
index 82f9ebeb..ea348eca 100644
--- a/plugins/supplicant.c
+++ b/plugins/supplicant.c
@@ -177,6 +177,7 @@ struct supplicant_task {
char *ifname;
struct connman_device *device;
struct connman_network *network;
+ struct connman_network *pending_network;
char *path;
char *netpath;
gboolean created;
@@ -184,6 +185,7 @@ struct supplicant_task {
gboolean noscan;
GSList *scan_results;
struct iw_range *range;
+ gboolean disconnecting;
};
static GSList *task_list = NULL;
@@ -1481,9 +1483,21 @@ static void state_change(struct supplicant_task *task, DBusMessage *msg)
connman_device_set_scanning(task->device, FALSE);
break;
case WPA_DISCONNECTED:
- /* carrier off */
- connman_network_set_connected(task->network, FALSE);
- connman_device_set_scanning(task->device, FALSE);
+ if (task->disconnecting == TRUE) {
+ connman_network_set_connected(task->network, FALSE);
+ connman_network_unref(task->network);
+ task->disconnecting = FALSE;
+
+ if (task->pending_network != NULL) {
+ task->network = task->pending_network;
+ task->pending_network = NULL;
+ task_connect(task);
+ }
+ } else {
+ /* carrier off */
+ connman_network_set_connected(task->network, FALSE);
+ connman_device_set_scanning(task->device, FALSE);
+ }
break;
case WPA_ASSOCIATING:
connman_network_set_associating(task->network, TRUE);
@@ -1581,6 +1595,8 @@ int supplicant_start(struct connman_device *device)
task->created = FALSE;
task->noscan = FALSE;
task->state = WPA_INVALID;
+ task->disconnecting = FALSE;
+ task->pending_network = NULL;
task_list = g_slist_append(task_list, task);
@@ -1658,9 +1674,14 @@ int supplicant_connect(struct connman_network *network)
if (task == NULL)
return -ENODEV;
- task->network = connman_network_ref(network);
+ if (task->disconnecting == TRUE)
+ task->pending_network = connman_network_ref(network);
+ else {
+ task->network = connman_network_ref(network);
+ return task_connect(task);
+ }
- return task_connect(task);
+ return 0;
}
int supplicant_disconnect(struct connman_network *network)
@@ -1676,13 +1697,14 @@ int supplicant_disconnect(struct connman_network *network)
if (task == NULL)
return -ENODEV;
+ if (task->disconnecting == TRUE)
+ return -EINPROGRESS;
+
disable_network(task);
remove_network(task);
- connman_network_set_connected(task->network, FALSE);
-
- connman_network_unref(task->network);
+ task->disconnecting = TRUE;
return 0;
}