diff options
author | Patrik Flykt <patrik.flykt@linux.intel.com> | 2012-11-09 10:54:20 +0200 |
---|---|---|
committer | Patrik Flykt <patrik.flykt@linux.intel.com> | 2012-11-13 14:37:45 +0200 |
commit | 0fb7d1f43b653a9057cdd35a42b4bc766655e72d (patch) | |
tree | 1ac119fd5ea63a9839908535a133a0699493495c /gsupplicant | |
parent | 3170b704fe7cc56a5e89439f632f1b7ba35e7602 (diff) | |
download | connman-0fb7d1f43b653a9057cdd35a42b4bc766655e72d.tar.gz connman-0fb7d1f43b653a9057cdd35a42b4bc766655e72d.tar.bz2 connman-0fb7d1f43b653a9057cdd35a42b4bc766655e72d.zip |
supplicant: Handle race condition on WiFi dongle removal
When a WiFi USB dongle is removed, both rtnl and wpa_supplicant will
be telling that the device is gone. While disconnecting and removing
an interface via gsupplicant, check that D-Bus doesn't give us an
error indicating the interface is already unregistered from D-Bus.
The gdb output looks like:
(gdb) where
#0 0x0042247c in network_connect (network=0x2) at plugins/wifi.c:1197
#1 0x004228f0 in disconnect_callback (result=<value optimized out>,
interface=0x0, user_data=0x99) at plugins/wifi.c:1254
#2 0x0042b910 in network_remove_result (error=0x4d5458
"org.freedesktop.DBus.Error.UnknownMethod", iter=<value optimized
out>,
user_data=<value optimized out>) at gsupplicant/supplicant.c:3593
#3 0x0042ede0 in method_call_reply (call=0x4c6fd0,
user_data=0x4d3be8) at gsupplicant/dbus.c:386
#4 0x2abfddb4 in complete_pending_call_and_unlock () from
/usr/lib/libdbus-1.so.3
Also don't call the same callback twice.
Diffstat (limited to 'gsupplicant')
-rw-r--r-- | gsupplicant/supplicant.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c index cd1225e2..d9dfdbb3 100644 --- a/gsupplicant/supplicant.c +++ b/gsupplicant/supplicant.c @@ -3586,8 +3586,12 @@ static void network_remove_result(const char *error, SUPPLICANT_DBG(""); - if (error != NULL) + if (error != NULL) { result = -EIO; + if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod", + error) == 0) + result = -ECONNABORTED; + } if (data->callback != NULL) data->callback(result, data->interface, data->user_data); @@ -3620,11 +3624,21 @@ static void interface_disconnect_result(const char *error, DBusMessageIter *iter, void *user_data) { struct interface_data *data = user_data; + int result = 0; SUPPLICANT_DBG(""); - if (error != NULL && data->callback != NULL) - data->callback(-EIO, data->interface, data->user_data); + if (error != NULL) { + result = -EIO; + if (g_strcmp0("org.freedesktop.DBus.Error.UnknownMethod", + error) == 0) + result = -ECONNABORTED; + } + + if (result < 0 && data->callback != NULL) { + data->callback(result, data->interface, data->user_data); + data->callback = NULL; + } /* If we are disconnecting from previous WPS successful * association. i.e.: it did not went through AddNetwork, @@ -3634,7 +3648,10 @@ static void interface_disconnect_result(const char *error, return; } - network_remove(data); + if (result != -ECONNABORTED) + network_remove(data); + else + dbus_free(data); } int g_supplicant_interface_disconnect(GSupplicantInterface *interface, |