NetworkManager r4105 - in trunk: . src
- From: dcbw svn gnome org
- To: svn-commits-list gnome org
- Subject: NetworkManager r4105 - in trunk: . src
- Date: Thu, 25 Sep 2008 10:02:28 +0000 (UTC)
Author: dcbw
Date: Thu Sep 25 10:02:28 2008
New Revision: 4105
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=4105&view=rev
Log:
2008-09-25 Dan Williams <dcbw redhat com>
Fix bgo #549401 (inspired by patch from Alexander Sack)
* src/nm-device-ethernet.c
- (finish_supplicant_task): clean up scheduled tasks and free memory
- (remove_supplicant_interface_error_handler): remove the supplicant
error idle callback too
- (supplicant_interface_release): rename from supplicant_interface_clean
to match nm-device-wifi.c; clean up supplicant interface-related
state tasks when the supplicant interface is disposed of
- (schedule_state_handler): add scheduled tasks to a list so they can
be cleaned up later
- (supplicant_mgr_state_cb_handler, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler): use
finish_supplicant_task() to clean up each completed task
- (supplicant_iface_connection_error_cb_handler,
supplicant_connection_timeout_cb): clear source id when the task is
complete
- (supplicant_iface_connection_error_cb): save scheduled task id for
later cleanup
- (nm_device_ethernet_dispose): clean up any pending supplicant state
tasks
* src/nm-device-wifi.c
- (finish_supplicant_task): clean up scheduled tasks and free memory
- (remove_supplicant_interface_error_handler): remove the supplicant
error idle callback too
- (supplicant_interface_release): clean up supplicant interface-related
state tasks when the supplicant interface is disposed of
- (schedule_state_handler): add scheduled tasks to a list so they can
be cleaned up later
- (supplicant_mgr_state_cb_handler, supplicant_iface_state_cb_handler,
supplicant_iface_connection_state_cb_handler): use
finish_supplicant_task() to clean up each completed task
- (supplicant_iface_connection_error_cb_handler): clear source id when
the task is complete
- (supplicant_iface_connection_error_cb): save scheduled task id for
later cleanup
- (nm_device_wifi_dispose): clean up any pending supplicant state tasks
Modified:
trunk/ChangeLog
trunk/src/nm-device-ethernet.c
trunk/src/nm-device-wifi.c
Modified: trunk/src/nm-device-ethernet.c
==============================================================================
--- trunk/src/nm-device-ethernet.c (original)
+++ trunk/src/nm-device-ethernet.c Thu Sep 25 10:02:28 2008
@@ -18,7 +18,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * (C) Copyright 2005 Red Hat, Inc.
+ * (C) Copyright 2005 - 2008 Red Hat, Inc.
*/
#include <glib.h>
@@ -73,17 +73,30 @@
#define NM_ETHERNET_ERROR (nm_ethernet_error_quark ())
#define NM_TYPE_ETHERNET_ERROR (nm_ethernet_error_get_type ())
+typedef struct SupplicantStateTask {
+ NMDeviceEthernet *self;
+ guint32 new_state;
+ guint32 old_state;
+ gboolean mgr_task;
+ guint source_id;
+} SupplicantStateTask;
+
typedef struct Supplicant {
NMSupplicantManager *mgr;
NMSupplicantInterface *iface;
/* signal handler ids */
- guint mgr_state_id;
- guint iface_error_id;
- guint iface_state_id;
- guint iface_con_state_id;
+ guint mgr_state_id;
+ guint iface_error_id;
+ guint iface_state_id;
+ guint iface_con_state_id;
+
+ /* Timeouts and idles */
+ guint iface_con_error_cb_id;
+ guint con_timeout_id;
- guint con_timeout_id;
+ GSList *iface_tasks;
+ GSList *mgr_tasks;
} Supplicant;
typedef struct {
@@ -664,7 +677,31 @@
}
static void
-remove_supplicant_interface_connection_error_handler (NMDeviceEthernet *self)
+finish_supplicant_task (SupplicantStateTask *task, gboolean remove_source)
+{
+ NMDeviceEthernet *self = task->self;
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
+
+ /* idle/timeout handlers should pass FALSE for remove_source, since they
+ * will tell glib to remove their source from the mainloop by returning
+ * FALSE when they exit. When called from this NMDevice's dispose handler,
+ * remove_source should be TRUE to cancel all outstanding idle/timeout
+ * handlers asynchronously.
+ */
+ if (task->source_id && remove_source)
+ g_source_remove (task->source_id);
+
+ if (task->mgr_task)
+ priv->supplicant.mgr_tasks = g_slist_remove (priv->supplicant.mgr_tasks, task);
+ else
+ priv->supplicant.iface_tasks = g_slist_remove (priv->supplicant.iface_tasks, task);
+
+ memset (task, 0, sizeof (SupplicantStateTask));
+ g_slice_free (SupplicantStateTask, task);
+}
+
+static void
+remove_supplicant_interface_error_handler (NMDeviceEthernet *self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
@@ -672,15 +709,24 @@
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id);
priv->supplicant.iface_error_id = 0;
}
+
+ if (priv->supplicant.iface_con_error_cb_id > 0) {
+ g_source_remove (priv->supplicant.iface_con_error_cb_id);
+ priv->supplicant.iface_con_error_cb_id = 0;
+ }
}
static void
-supplicant_interface_clean (NMDeviceEthernet *self)
+supplicant_interface_release (NMDeviceEthernet *self)
{
NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
remove_supplicant_timeouts (self);
- remove_supplicant_interface_connection_error_handler (self);
+ remove_supplicant_interface_error_handler (self);
+
+ /* Clean up all pending supplicant interface state idle tasks */
+ while (priv->supplicant.iface_tasks)
+ finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.iface_tasks->data, TRUE);
if (priv->supplicant.iface_con_state_id) {
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_con_state_id);
@@ -739,7 +785,7 @@
nm_info ("Activation (%s/wired): disconnected during authentication,"
" asking for new key.", nm_device_get_iface (dev));
- supplicant_interface_clean (self);
+ supplicant_interface_release (self);
nm_device_state_changed (dev, NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT);
nm_act_request_request_connection_secrets (req, setting_name, TRUE,
@@ -754,42 +800,47 @@
return FALSE;
}
-struct state_cb_data {
- NMDeviceEthernet *self;
- guint32 new_state;
- guint32 old_state;
-};
-
static gboolean
schedule_state_handler (NMDeviceEthernet *self,
GSourceFunc handler,
guint32 new_state,
- guint32 old_state)
+ guint32 old_state,
+ gboolean mgr_task)
{
- struct state_cb_data * cb_data;
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
+ SupplicantStateTask *task;
if (new_state == old_state)
return TRUE;
- cb_data = g_slice_new0 (struct state_cb_data);
- cb_data->self = self;
- cb_data->new_state = new_state;
- cb_data->old_state = old_state;
-
- g_idle_add (handler, cb_data);
+ task = g_slice_new0 (SupplicantStateTask);
+ if (!task) {
+ nm_warning ("Not enough memory to process supplicant manager state change.");
+ return FALSE;
+ }
+ task->self = self;
+ task->new_state = new_state;
+ task->old_state = old_state;
+ task->mgr_task = mgr_task;
+
+ task->source_id = g_idle_add (handler, task);
+ if (mgr_task)
+ priv->supplicant.mgr_tasks = g_slist_append (priv->supplicant.mgr_tasks, task);
+ else
+ priv->supplicant.iface_tasks = g_slist_append (priv->supplicant.iface_tasks, task);
return TRUE;
}
static gboolean
supplicant_mgr_state_cb_handler (gpointer user_data)
{
- struct state_cb_data *info = (struct state_cb_data *) user_data;
- NMDevice *device = NM_DEVICE (info->self);
+ SupplicantStateTask *task = (SupplicantStateTask *) user_data;
+ NMDevice *device = NM_DEVICE (task->self);
/* If the supplicant went away, release the supplicant interface */
- if (info->new_state == NM_SUPPLICANT_MANAGER_STATE_DOWN) {
- supplicant_interface_clean (info->self);
+ if (task->new_state == NM_SUPPLICANT_MANAGER_STATE_DOWN) {
+ supplicant_interface_release (task->self);
if (nm_device_get_state (device) > NM_DEVICE_STATE_UNAVAILABLE) {
nm_device_state_changed (device, NM_DEVICE_STATE_UNAVAILABLE,
@@ -797,8 +848,7 @@
}
}
- g_slice_free (struct state_cb_data, info);
-
+ finish_supplicant_task (task, FALSE);
return FALSE;
}
@@ -814,8 +864,10 @@
old_state);
schedule_state_handler (NM_DEVICE_ETHERNET (user_data),
- supplicant_mgr_state_cb_handler,
- new_state, old_state);
+ supplicant_mgr_state_cb_handler,
+ new_state,
+ old_state,
+ TRUE);
}
static NMSupplicantConfig *
@@ -848,17 +900,17 @@
static gboolean
supplicant_iface_state_cb_handler (gpointer user_data)
{
- struct state_cb_data *info = (struct state_cb_data *) user_data;
- NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (info->self);
- NMDevice *device = NM_DEVICE (info->self);
+ SupplicantStateTask *task = (SupplicantStateTask *) user_data;
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (task->self);
+ NMDevice *device = NM_DEVICE (task->self);
- if (info->new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
+ if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
NMSupplicantConfig *config;
const char *iface;
gboolean success = FALSE;
iface = nm_device_get_iface (device);
- config = build_supplicant_config (info->self);
+ config = build_supplicant_config (task->self);
if (config) {
success = nm_supplicant_interface_set_config (priv->supplicant.iface, config);
g_object_unref (config);
@@ -871,17 +923,16 @@
if (!success)
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
- } else if (info->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
+ } else if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
NMDeviceState state = nm_device_get_state (device);
- supplicant_interface_clean (info->self);
+ supplicant_interface_release (task->self);
if (nm_device_is_activating (device) || state == NM_DEVICE_STATE_ACTIVATED)
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
}
- g_slice_free (struct state_cb_data, info);
-
+ finish_supplicant_task (task, FALSE);
return FALSE;
}
@@ -900,18 +951,19 @@
schedule_state_handler (NM_DEVICE_ETHERNET (user_data),
supplicant_iface_state_cb_handler,
new_state,
- old_state);
+ old_state,
+ FALSE);
}
static gboolean
supplicant_iface_connection_state_cb_handler (gpointer user_data)
{
- struct state_cb_data *info = (struct state_cb_data *) user_data;
- NMDevice *dev = NM_DEVICE (info->self);
+ SupplicantStateTask *task = (SupplicantStateTask *) user_data;
+ NMDevice *dev = NM_DEVICE (task->self);
- if (info->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) {
- remove_supplicant_interface_connection_error_handler (info->self);
- remove_supplicant_timeouts (info->self);
+ if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) {
+ remove_supplicant_interface_error_handler (task->self);
+ remove_supplicant_timeouts (task->self);
/* If this is the initial association during device activation,
* schedule the next activation stage.
@@ -921,9 +973,9 @@
nm_device_get_iface (dev));
nm_device_activate_schedule_stage3_ip_config_start (dev);
}
- } else if (info->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED) {
+ } else if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED) {
if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED || nm_device_is_activating (dev)) {
- NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (info->self);
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (task->self);
/* Start the link timeout so we allow some time for reauthentication */
if (!priv->link_timeout_id)
@@ -931,8 +983,7 @@
}
}
- g_slice_free (struct state_cb_data, info);
-
+ finish_supplicant_task (task, FALSE);
return FALSE;
}
@@ -948,17 +999,20 @@
schedule_state_handler (NM_DEVICE_ETHERNET (user_data),
supplicant_iface_connection_state_cb_handler,
new_state,
- old_state);
+ old_state,
+ FALSE);
}
static gboolean
supplicant_iface_connection_error_cb_handler (gpointer user_data)
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
- supplicant_interface_clean (self);
+ supplicant_interface_release (self);
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
+ priv->supplicant.iface_con_error_cb_id = 0;
return FALSE;
}
@@ -968,12 +1022,18 @@
const char *message,
gpointer user_data)
{
- NMDevice *device = NM_DEVICE (user_data);
+ NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
+ guint id;
nm_info ("Activation (%s/wired): association request to the supplicant failed: %s - %s",
- nm_device_get_iface (device), name, message);
+ nm_device_get_iface (NM_DEVICE (self)), name, message);
+
+ if (priv->supplicant.iface_con_error_cb_id)
+ g_source_remove (priv->supplicant.iface_con_error_cb_id);
- g_idle_add (supplicant_iface_connection_error_cb_handler, device);
+ id = g_idle_add (supplicant_iface_connection_error_cb_handler, self);
+ priv->supplicant.iface_con_error_cb_id = id;
}
static NMActStageReturn
@@ -1017,16 +1077,19 @@
supplicant_connection_timeout_cb (gpointer user_data)
{
NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data);
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
NMDevice *device = NM_DEVICE (self);
NMActRequest *req;
const char *iface;
+ priv->supplicant.con_timeout_id = 0;
+
iface = nm_device_get_iface (device);
/* Authentication failed, encryption key is probably bad */
nm_info ("Activation (%s/wired): association took too long.", iface);
- supplicant_interface_clean (self);
+ supplicant_interface_release (self);
req = nm_device_get_act_request (device);
g_assert (req);
@@ -1050,7 +1113,7 @@
priv->supplicant.iface = nm_supplicant_manager_get_iface (priv->supplicant.mgr, iface, FALSE);
if (!priv->supplicant.iface) {
nm_warning ("Couldn't initialize supplicant interface for %s.", iface);
- supplicant_interface_clean (self);
+ supplicant_interface_release (self);
return FALSE;
}
@@ -1290,7 +1353,7 @@
priv->ppp_manager = NULL;
}
- supplicant_interface_clean (NM_DEVICE_ETHERNET (device));
+ supplicant_interface_release (NM_DEVICE_ETHERNET (device));
}
static gboolean
@@ -1345,7 +1408,8 @@
static void
nm_device_ethernet_dispose (GObject *object)
{
- NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (object);
+ NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object);
+ NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self);
NMNetlinkMonitor *monitor;
if (priv->dispose_has_run) {
@@ -1355,6 +1419,12 @@
priv->dispose_has_run = TRUE;
+ /* Clean up all pending supplicant tasks */
+ while (priv->supplicant.iface_tasks)
+ finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.iface_tasks->data, TRUE);
+ while (priv->supplicant.mgr_tasks)
+ finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.mgr_tasks->data, TRUE);
+
monitor = nm_netlink_monitor_get ();
if (priv->link_connected_id) {
g_signal_handler_disconnect (monitor, priv->link_connected_id);
Modified: trunk/src/nm-device-wifi.c
==============================================================================
--- trunk/src/nm-device-wifi.c (original)
+++ trunk/src/nm-device-wifi.c Thu Sep 25 10:02:28 2008
@@ -17,7 +17,8 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * (C) Copyright 2005 Red Hat, Inc.
+ * (C) Copyright 2005 - 2008 Red Hat, Inc.
+ * (C) Copyright 2007 - 2008 Novell, Inc.
*/
#include <glib.h>
@@ -106,20 +107,32 @@
#define NM_WIFI_ERROR (nm_wifi_error_quark ())
#define NM_TYPE_WIFI_ERROR (nm_wifi_error_get_type ())
+typedef struct SupplicantStateTask {
+ NMDeviceWifi *self;
+ guint32 new_state;
+ guint32 old_state;
+ gboolean mgr_task;
+ guint source_id;
+} SupplicantStateTask;
typedef struct Supplicant {
NMSupplicantManager * mgr;
NMSupplicantInterface * iface;
/* signal handler ids */
- guint mgr_state_id;
- guint iface_error_id;
- guint iface_state_id;
- guint iface_scanned_ap_id;
- guint iface_scan_result_id;
- guint iface_con_state_id;
+ guint mgr_state_id;
+ guint iface_error_id;
+ guint iface_state_id;
+ guint iface_scanned_ap_id;
+ guint iface_scan_result_id;
+ guint iface_con_state_id;
+
+ /* Timeouts and idles */
+ guint iface_con_error_cb_id;
+ guint con_timeout_id;
- guint con_timeout_id;
+ GSList *mgr_tasks;
+ GSList *iface_tasks;
} Supplicant;
struct _NMDeviceWifiPrivate
@@ -147,11 +160,11 @@
guint8 scan_interval; /* seconds */
guint pending_scan_id;
- Supplicant supplicant;
+ Supplicant supplicant;
- guint32 failed_link_count;
- guint periodic_source_id;
- guint link_timeout_id;
+ guint32 failed_link_count;
+ guint periodic_source_id;
+ guint link_timeout_id;
/* Static options from driver */
guint8 we_version;
@@ -405,7 +418,6 @@
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
priv->dispose_has_run = FALSE;
- priv->supplicant.iface_error_id = 0;
priv->scanning = FALSE;
priv->ap_list = NULL;
priv->we_version = 0;
@@ -590,6 +602,49 @@
}
static void
+finish_supplicant_task (SupplicantStateTask *task, gboolean remove_source)
+{
+ NMDeviceWifi *self = task->self;
+ NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+ /* idle/timeout handlers should pass FALSE for remove_source, since they
+ * will tell glib to remove their source from the mainloop by returning
+ * FALSE when they exit. When called from this NMDevice's dispose handler,
+ * remove_source should be TRUE to cancel all outstanding idle/timeout
+ * handlers asynchronously.
+ */
+ if (task->source_id && remove_source)
+ g_source_remove (task->source_id);
+
+ if (task->mgr_task)
+ priv->supplicant.mgr_tasks = g_slist_remove (priv->supplicant.mgr_tasks, task);
+ else
+ priv->supplicant.iface_tasks = g_slist_remove (priv->supplicant.iface_tasks, task);
+
+ memset (task, 0, sizeof (SupplicantStateTask));
+ g_slice_free (SupplicantStateTask, task);
+}
+
+static void
+remove_supplicant_interface_error_handler (NMDeviceWifi *self)
+{
+ NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+ if (!priv->supplicant.iface)
+ return;
+
+ if (priv->supplicant.iface_error_id > 0) {
+ g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id);
+ priv->supplicant.iface_error_id = 0;
+ }
+
+ if (priv->supplicant.iface_con_error_cb_id > 0) {
+ g_source_remove (priv->supplicant.iface_con_error_cb_id);
+ priv->supplicant.iface_con_error_cb_id = 0;
+ }
+}
+
+static void
supplicant_interface_release (NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv;
@@ -603,10 +658,11 @@
/* Reset the scan interval to be pretty frequent when disconnected */
priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP;
- if (priv->supplicant.iface_error_id > 0) {
- g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_error_id);
- priv->supplicant.iface_error_id = 0;
- }
+ remove_supplicant_interface_error_handler (self);
+
+ /* Clean up all pending supplicant interface state idle tasks */
+ while (priv->supplicant.iface_tasks)
+ finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.iface_tasks->data, TRUE);
if (priv->supplicant.iface_state_id > 0) {
g_signal_handler_disconnect (priv->supplicant.iface, priv->supplicant.iface_state_id);
@@ -1945,26 +2001,11 @@
static void
-remove_supplicant_interface_connection_error_handler (NMDeviceWifi *self)
-{
- NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-
- if (!priv->supplicant.iface)
- return;
-
- if (priv->supplicant.iface_error_id != 0) {
- g_signal_handler_disconnect (priv->supplicant.iface,
- priv->supplicant.iface_error_id);
- priv->supplicant.iface_error_id = 0;
- }
-}
-
-static void
cleanup_association_attempt (NMDeviceWifi *self, gboolean disconnect)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
- remove_supplicant_interface_connection_error_handler (self);
+ remove_supplicant_interface_error_handler (self);
remove_supplicant_timeouts (self);
if (disconnect && priv->supplicant.iface)
nm_supplicant_interface_disconnect (priv->supplicant.iface);
@@ -2074,20 +2115,15 @@
return FALSE;
}
-
-struct state_cb_data {
- NMDeviceWifi * self;
- guint32 new_state;
- guint32 old_state;
-};
-
static gboolean
-schedule_state_handler (NMDeviceWifi * self,
+schedule_state_handler (NMDeviceWifi *self,
GSourceFunc handler,
guint32 new_state,
- guint32 old_state)
+ guint32 old_state,
+ gboolean mgr_task)
{
- struct state_cb_data * cb_data;
+ NMDeviceWifiPrivate *priv;
+ SupplicantStateTask *task;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (handler != NULL, FALSE);
@@ -2095,18 +2131,24 @@
if (new_state == old_state)
return TRUE;
- cb_data = g_slice_new0 (struct state_cb_data);
- if (cb_data == NULL) {
- nm_warning ("Not enough memory to process supplicant manager state"
- " change.");
+ priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+ task = g_slice_new0 (SupplicantStateTask);
+ if (!task) {
+ nm_warning ("Not enough memory to process supplicant manager state change.");
return FALSE;
}
- cb_data->self = self;
- cb_data->new_state = new_state;
- cb_data->old_state = old_state;
-
- g_idle_add (handler, cb_data);
+ task->self = self;
+ task->new_state = new_state;
+ task->old_state = old_state;
+ task->mgr_task = mgr_task;
+
+ task->source_id = g_idle_add (handler, task);
+ if (mgr_task)
+ priv->supplicant.mgr_tasks = g_slist_append (priv->supplicant.mgr_tasks, task);
+ else
+ priv->supplicant.iface_tasks = g_slist_append (priv->supplicant.iface_tasks, task);
return TRUE;
}
@@ -2114,37 +2156,34 @@
static gboolean
supplicant_iface_state_cb_handler (gpointer user_data)
{
- struct state_cb_data *cb_data = (struct state_cb_data *) user_data;
+ SupplicantStateTask *task = (SupplicantStateTask *) user_data;
NMDeviceWifi *self;
NMDeviceWifiPrivate *priv;
- guint32 new_state, old_state;
- g_return_val_if_fail (cb_data != NULL, FALSE);
+ g_return_val_if_fail (task != NULL, FALSE);
- self = cb_data->self;
+ self = task->self;
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
- new_state = cb_data->new_state;
- old_state = cb_data->old_state;
nm_info ("(%s): supplicant interface state change: %d -> %d.",
nm_device_get_iface (NM_DEVICE (self)),
- old_state,
- new_state);
+ task->old_state,
+ task->new_state);
- if (new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
+ if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
priv->scan_interval = SCAN_INTERVAL_MIN;
/* Request a scan to get latest results */
cancel_pending_scan (self);
request_wireless_scan (self);
- } else if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
+ } else if (task->new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
cleanup_association_attempt (self, FALSE);
supplicant_interface_release (self);
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE,
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
}
-
- g_slice_free (struct state_cb_data, cb_data);
+
+ finish_supplicant_task (task, FALSE);
return FALSE;
}
@@ -2160,19 +2199,18 @@
schedule_state_handler (self,
supplicant_iface_state_cb_handler,
new_state,
- old_state);
+ old_state,
+ FALSE);
}
static gboolean
supplicant_iface_connection_state_cb_handler (gpointer user_data)
{
- struct state_cb_data *cb_data = (struct state_cb_data *) user_data;
- NMDeviceWifi *self = cb_data->self;
+ SupplicantStateTask *task = (SupplicantStateTask *) user_data;
+ NMDeviceWifi *self = task->self;
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
NMDevice *dev = NM_DEVICE (self);
- guint32 new_state = cb_data->new_state;
- guint32 old_state = cb_data->old_state;
if (!nm_device_get_act_request (dev)) {
/* The device is not activating or already activated; do nothing. */
@@ -2180,12 +2218,12 @@
}
nm_info ("(%s): supplicant connection state change: %d -> %d",
- nm_device_get_iface (dev), old_state, new_state);
+ nm_device_get_iface (dev), task->old_state, task->new_state);
- priv->scanning = (new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING);
+ priv->scanning = (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_SCANNING);
- if (new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) {
- remove_supplicant_interface_connection_error_handler (self);
+ if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_COMPLETED) {
+ remove_supplicant_interface_error_handler (self);
remove_supplicant_timeouts (self);
/* If this is the initial association during device activation,
@@ -2201,7 +2239,7 @@
ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)");
nm_device_activate_schedule_stage3_ip_config_start (dev);
}
- } else if (new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED) {
+ } else if (task->new_state == NM_SUPPLICANT_INTERFACE_CON_STATE_DISCONNECTED) {
if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED || nm_device_is_activating (dev)) {
/* Start the link timeout so we allow some time for reauthentication,
* use a longer timeout if we are scanning since some cards take a
@@ -2215,7 +2253,7 @@
}
out:
- g_slice_free (struct state_cb_data, cb_data);
+ finish_supplicant_task (task, FALSE);
return FALSE;
}
@@ -2231,35 +2269,32 @@
schedule_state_handler (self,
supplicant_iface_connection_state_cb_handler,
new_state,
- old_state);
+ old_state,
+ FALSE);
}
static gboolean
supplicant_mgr_state_cb_handler (gpointer user_data)
{
- struct state_cb_data * cb_data = (struct state_cb_data *) user_data;
+ SupplicantStateTask *task = (SupplicantStateTask *) user_data;
NMDeviceWifi *self;
NMDeviceWifiPrivate *priv;
NMDevice *dev;
- guint32 new_state, old_state;
NMDeviceState dev_state;
- g_return_val_if_fail (cb_data != NULL, FALSE);
+ g_return_val_if_fail (task != NULL, FALSE);
- self = cb_data->self;
+ self = task->self;
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
dev = NM_DEVICE (self);
- new_state = cb_data->new_state;
- old_state = cb_data->old_state;
nm_info ("(%s): supplicant manager is now in state %d (from %d).",
nm_device_get_iface (NM_DEVICE (self)),
- new_state,
- old_state);
+ task->new_state, task->old_state);
/* If the supplicant went away, release the supplicant interface */
- if (new_state == NM_SUPPLICANT_MANAGER_STATE_DOWN) {
+ if (task->new_state == NM_SUPPLICANT_MANAGER_STATE_DOWN) {
if (priv->supplicant.iface) {
cleanup_association_attempt (self, FALSE);
supplicant_interface_release (self);
@@ -2269,7 +2304,7 @@
nm_device_state_changed (dev, NM_DEVICE_STATE_UNAVAILABLE,
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
}
- } else if (new_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) {
+ } else if (task->new_state == NM_SUPPLICANT_MANAGER_STATE_IDLE) {
dev_state = nm_device_get_state (dev);
if ( priv->enabled
&& !priv->supplicant.iface
@@ -2287,7 +2322,7 @@
}
}
- g_slice_free (struct state_cb_data, cb_data);
+ finish_supplicant_task (task, FALSE);
return FALSE;
}
@@ -2302,25 +2337,27 @@
schedule_state_handler (self,
supplicant_mgr_state_cb_handler,
new_state,
- old_state);
+ old_state,
+ TRUE);
}
struct iface_con_error_cb_data {
- NMDeviceWifi * self;
- char * name;
- char * message;
+ NMDeviceWifi *self;
+ char *name;
+ char *message;
};
-
static gboolean
supplicant_iface_connection_error_cb_handler (gpointer user_data)
{
+ NMDeviceWifi *self;
+ NMDeviceWifiPrivate *priv;
struct iface_con_error_cb_data * cb_data = (struct iface_con_error_cb_data *) user_data;
- NMDeviceWifi * self;
g_return_val_if_fail (cb_data != NULL, FALSE);
self = cb_data->self;
+ priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
if (!nm_device_is_activating (NM_DEVICE (self)))
goto out;
@@ -2335,6 +2372,7 @@
nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
out:
+ priv->supplicant.iface_con_error_cb_id = 0;
g_free (cb_data->name);
g_free (cb_data->message);
g_slice_free (struct iface_con_error_cb_data, cb_data);
@@ -2348,10 +2386,12 @@
const char * message,
NMDeviceWifi * self)
{
- struct iface_con_error_cb_data * cb_data;
- guint id;
+ NMDeviceWifiPrivate *priv;
+ struct iface_con_error_cb_data *cb_data;
+ guint id;
g_return_if_fail (self != NULL);
+ priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
cb_data = g_slice_new0 (struct iface_con_error_cb_data);
if (cb_data == NULL) {
@@ -2363,7 +2403,11 @@
cb_data->name = g_strdup (name);
cb_data->message = g_strdup (message);
+ if (priv->supplicant.iface_con_error_cb_id)
+ g_source_remove (priv->supplicant.iface_con_error_cb_id);
+
id = g_idle_add (supplicant_iface_connection_error_cb_handler, cb_data);
+ priv->supplicant.iface_con_error_cb_id = id;
}
static void
@@ -3095,6 +3139,12 @@
priv->periodic_source_id = 0;
}
+ /* Clean up all pending supplicant tasks */
+ while (priv->supplicant.iface_tasks)
+ finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.iface_tasks->data, TRUE);
+ while (priv->supplicant.mgr_tasks)
+ finish_supplicant_task ((SupplicantStateTask *) priv->supplicant.mgr_tasks->data, TRUE);
+
cleanup_association_attempt (self, TRUE);
supplicant_interface_release (self);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]