diff options
author | Martin Xu <martin.xu@intel.com> | 2009-07-10 12:29:36 +0800 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2009-07-09 22:28:18 -0700 |
commit | 1ef7930086f2d99bbaa523609fcdb8cc47753356 (patch) | |
tree | 5e5f2bc87d79a63a577efd07f40113793f6e2d77 /plugins | |
parent | 50362b15a291893ec4a79168a24c6b2be3e6558a (diff) | |
download | connman-1ef7930086f2d99bbaa523609fcdb8cc47753356.tar.gz connman-1ef7930086f2d99bbaa523609fcdb8cc47753356.tar.bz2 connman-1ef7930086f2d99bbaa523609fcdb8cc47753356.zip |
Fix disconnect race condition issue in WiFi supplicant
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/supplicant.c | 38 |
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; } |