2006-12-28 Dan Williams <dcbw@redhat.com>

Use a single thread for everything.  With the move to wpa_supplicant
	and communication over D-Bus, there's no reason for multiple threads.
	Almost all of the blocking code has been removed, with one exception in
	the DHCP manager and a few in the VPN manager.  This commit removes the
	per-device worker thread and fixes activation cancellation in the absence
	of threads.  Further removal of thread-related code would be removing
	any locking code (like the device list lock) and simplification of logic
	around areas of code or data structures that are currently locked.

	* autoip.c
	  dhcp-manager/nm-dhcp-manager.c
	  nm-device-802-11-wireless.c
	  nm-device-802-3-ethernet.c
	  nm-device.c
	  nm-device.h
		- Remove usage of multiple threads


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2197 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams
2006-12-28 22:13:59 +00:00
parent 89d698ef95
commit a423162b36
7 changed files with 195 additions and 368 deletions

View File

@@ -1,3 +1,22 @@
2006-12-28 Dan Williams <dcbw@redhat.com>
Use a single thread for everything. With the move to wpa_supplicant
and communication over D-Bus, there's no reason for multiple threads.
Almost all of the blocking code has been removed, with one exception in
the DHCP manager and a few in the VPN manager. This commit removes the
per-device worker thread and fixes activation cancellation in the absence
of threads. Further removal of thread-related code would be removing
any locking code (like the device list lock) and simplification of logic
around areas of code or data structures that are currently locked.
* autoip.c
dhcp-manager/nm-dhcp-manager.c
nm-device-802-11-wireless.c
nm-device-802-3-ethernet.c
nm-device.c
nm-device.h
- Remove usage of multiple threads
2006-12-19 Dan Williams <dcbw@redhat.com> 2006-12-19 Dan Williams <dcbw@redhat.com>
Big wpa_supplicant + dbus update; need latest wpa_supplicant from CVS Big wpa_supplicant + dbus update; need latest wpa_supplicant from CVS

View File

@@ -198,8 +198,6 @@ static int peekfd (NMDevice *dev, int sk, struct timeval *timeout)
return RET_ERROR; return RET_ERROR;
if (FD_ISSET(sk, &fs)) if (FD_ISSET(sk, &fs))
return RET_SUCCESS; return RET_SUCCESS;
if (nm_device_activation_should_cancel (dev))
return RET_CEASED;
gettimeofday (&now, NULL); gettimeofday (&now, NULL);
}; };
return RET_TIMEOUT; return RET_TIMEOUT;
@@ -262,10 +260,6 @@ gboolean get_autoip (NMDevice *dev, struct in_addr *out_ip)
struct timeval timeout; struct timeval timeout;
int err; int err;
/* Make sure we haven't been told to quit */
if (nm_device_activation_should_cancel (dev))
goto out;
if (nprobes < PROBE_NUM) if (nprobes < PROBE_NUM)
{ {
nm_info ("autoip: Sending probe #%d for IP address %s.", nprobes, inet_ntoa (ip)); nm_info ("autoip: Sending probe #%d for IP address %s.", nprobes, inet_ntoa (ip));

View File

@@ -560,12 +560,9 @@ nm_completion_dhcp_bound_test (int tries,
nm_completion_args args) nm_completion_args args)
{ {
NMActRequest * req = args[0]; NMActRequest * req = args[0];
NMDevice * dev = args[1];
if (state_is_bound (nm_act_request_get_dhcp_state (req))) if (state_is_bound (nm_act_request_get_dhcp_state (req)))
return TRUE; return TRUE;
if (nm_device_activation_should_cancel (dev))
return TRUE;
return FALSE; return FALSE;
} }
@@ -618,8 +615,6 @@ nm_dhcp_manager_get_ip4_config (NMDHCPManager *manager,
args[1] = dev; args[1] = dev;
nm_wait_for_completion (30, G_USEC_PER_SEC / 10, nm_wait_for_completion (30, G_USEC_PER_SEC / 10,
nm_completion_dhcp_bound_test, NULL, args); nm_completion_dhcp_bound_test, NULL, args);
if (nm_device_activation_should_cancel (dev))
return NULL;
if (!state_is_bound (nm_act_request_get_dhcp_state (req))) { if (!state_is_bound (nm_act_request_get_dhcp_state (req))) {
nm_warning ("Tried to get IP4 Config for a device when dhcdbd " nm_warning ("Tried to get IP4 Config for a device when dhcdbd "

View File

@@ -2785,6 +2785,7 @@ remove_supplicant_connection_timeout (NMDevice80211Wireless *self)
/* Remove any pending timeouts on the request */ /* Remove any pending timeouts on the request */
if (self->priv->supplicant.con_timeout != NULL) { if (self->priv->supplicant.con_timeout != NULL) {
g_source_destroy (self->priv->supplicant.con_timeout); g_source_destroy (self->priv->supplicant.con_timeout);
g_source_unref (self->priv->supplicant.con_timeout);
self->priv->supplicant.con_timeout = NULL; self->priv->supplicant.con_timeout = NULL;
} }
} }
@@ -2834,6 +2835,35 @@ supplicant_connection_timeout_cb (gpointer user_data)
} }
static gboolean
start_supplicant_connection_timeout (NMDevice80211Wireless *self)
{
GMainContext * context;
NMDevice * dev;
g_return_val_if_fail (self != NULL, FALSE);
dev = NM_DEVICE (self);
/* Set up a timeout on the connection attempt to fail it after 25 seconds */
self->priv->supplicant.con_timeout = g_timeout_source_new (25000);
if (self->priv->supplicant.con_timeout == NULL) {
nm_warning ("Activation (%s/wireless): couldn't start supplicant "
"timeout timer.",
nm_device_get_iface (dev));
return FALSE;
}
g_source_set_callback (self->priv->supplicant.con_timeout,
supplicant_connection_timeout_cb,
self,
NULL);
context = nm_device_get_main_context (dev);
g_source_attach (self->priv->supplicant.con_timeout, context);
return TRUE;
}
static void static void
remove_supplicant_timeouts (NMDevice80211Wireless *self) remove_supplicant_timeouts (NMDevice80211Wireless *self)
{ {
@@ -2912,7 +2942,6 @@ real_act_stage2_config (NMDevice *dev,
const char * iface = nm_device_get_iface (dev); const char * iface = nm_device_get_iface (dev);
gboolean ask_user = FALSE; gboolean ask_user = FALSE;
NMSupplicantConfig * config = NULL; NMSupplicantConfig * config = NULL;
GMainContext * context;
gulong id = 0; gulong id = 0;
g_assert (ap); g_assert (ap);
@@ -2932,9 +2961,6 @@ real_act_stage2_config (NMDevice *dev,
goto out; goto out;
} }
if (nm_device_activation_should_cancel (NM_DEVICE (self)))
goto out;
/* Hook up error signal handler to capture association errors */ /* Hook up error signal handler to capture association errors */
id = g_signal_connect (G_OBJECT (self->priv->supplicant.iface), id = g_signal_connect (G_OBJECT (self->priv->supplicant.iface),
"connection-error", "connection-error",
@@ -2948,19 +2974,8 @@ real_act_stage2_config (NMDevice *dev,
goto out; goto out;
} }
/* Set up a timeout on the connection attempt to fail it after 25 seconds */ if (!start_supplicant_connection_timeout (self))
self->priv->supplicant.con_timeout = g_timeout_source_new (25000);
if (!self->priv->supplicant.con_timeout) {
nm_warning ("Activation (%s/wireless): couldn't start supplicant "
"timeout timer.", iface);
goto out; goto out;
}
g_source_set_callback (self->priv->supplicant.con_timeout,
supplicant_connection_timeout_cb,
self,
NULL);
context = nm_device_get_main_context (dev);
g_source_attach (self->priv->supplicant.con_timeout, context);
/* We'll get stage3 started when the supplicant connects */ /* We'll get stage3 started when the supplicant connects */
ret = NM_ACT_STAGE_RETURN_POSTPONE; ret = NM_ACT_STAGE_RETURN_POSTPONE;
@@ -3188,6 +3203,8 @@ real_activation_cancel_handler (NMDevice *dev,
if (nm_act_request_get_stage (req) == NM_ACT_STAGE_NEED_USER_KEY) if (nm_act_request_get_stage (req) == NM_ACT_STAGE_NEED_USER_KEY)
nm_dbus_cancel_get_user_key_for_network (req); nm_dbus_cancel_get_user_key_for_network (req);
cleanup_association_attempt (self, TRUE);
} }

View File

@@ -110,57 +110,33 @@ real_init (NMDevice *dev)
g_object_unref (sup_mgr); g_object_unref (sup_mgr);
} }
static gboolean
link_activated_helper (NMDevice8023Ethernet *self)
{
nm_device_set_active_link (NM_DEVICE (self), TRUE);
return FALSE;
}
static void static void
nm_device_802_3_ethernet_link_activated (NmNetlinkMonitor *monitor, nm_device_802_3_ethernet_link_activated (NmNetlinkMonitor *monitor,
GObject *obj, GObject *obj,
NMDevice8023Ethernet *self) NMDevice8023Ethernet *self)
{ {
NMDevice * dev = NM_DEVICE (self);
/* Make sure signal is for us */ /* Make sure signal is for us */
if (NM_DEVICE (self) != NM_DEVICE (obj)) if (dev != NM_DEVICE (obj))
return; return;
if (!nm_device_has_active_link (NM_DEVICE (self))) nm_device_set_active_link (dev, TRUE);
{
GSource * source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) link_activated_helper, self, NULL);
g_source_attach (source, nm_device_get_main_context (NM_DEVICE (self)));
g_source_unref (source);
}
} }
static gboolean
link_deactivated_helper (NMDevice8023Ethernet *self)
{
nm_device_set_active_link (NM_DEVICE (self), FALSE);
return FALSE;
}
static void static void
nm_device_802_3_ethernet_link_deactivated (NmNetlinkMonitor *monitor, nm_device_802_3_ethernet_link_deactivated (NmNetlinkMonitor *monitor,
GObject *obj, GObject *obj,
NMDevice8023Ethernet *self) NMDevice8023Ethernet *self)
{ {
NMDevice * dev = NM_DEVICE (self);
/* Make sure signal is for us */ /* Make sure signal is for us */
if (NM_DEVICE (self) != NM_DEVICE (obj)) if (dev != NM_DEVICE (obj))
return; return;
if (nm_device_has_active_link (NM_DEVICE (self))) nm_device_set_active_link (dev, FALSE);
{
GSource * source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) link_deactivated_helper, self, NULL);
g_source_attach (source, nm_device_get_main_context (NM_DEVICE (self)));
g_source_unref (source);
}
} }
static gboolean static gboolean
@@ -316,6 +292,22 @@ real_get_generic_capabilities (NMDevice *dev)
return caps; return caps;
} }
static gboolean
real_can_interrupt_activation (NMDevice *dev)
{
gboolean interrupt = FALSE;
/* Devices that support carrier detect can interrupt activation
* if the link becomes inactive.
*/
if (nm_device_get_capabilities (dev) & NM_DEVICE_CAP_CARRIER_DETECT) {
if (nm_device_has_active_link (dev) == FALSE) {
interrupt = TRUE;
}
}
return interrupt;
}
static void static void
nm_device_802_3_ethernet_dispose (GObject *object) nm_device_802_3_ethernet_dispose (GObject *object)
{ {
@@ -381,6 +373,7 @@ nm_device_802_3_ethernet_class_init (NMDevice8023EthernetClass *klass)
parent_class->init = real_init; parent_class->init = real_init;
parent_class->start = real_start; parent_class->start = real_start;
parent_class->update_link = real_update_link; parent_class->update_link = real_update_link;
parent_class->can_interrupt_activation = real_can_interrupt_activation;
g_type_class_add_private (object_class, sizeof (NMDevice8023EthernetPrivate)); g_type_class_add_private (object_class, sizeof (NMDevice8023EthernetPrivate));
} }

View File

@@ -58,7 +58,7 @@ struct _NMDevicePrivate
NMData * app_data; NMData * app_data;
NMActRequest * act_request; NMActRequest * act_request;
gboolean quit_activation; GSource * act_source;
/* IP configuration info */ /* IP configuration info */
void * system_config_data; /* Distro-specific config data (parsed config file, etc) */ void * system_config_data; /* Distro-specific config data (parsed config file, etc) */
@@ -66,15 +66,13 @@ struct _NMDevicePrivate
NMIP4Config * ip4_config; /* Config from DHCP, PPP, or system config files */ NMIP4Config * ip4_config; /* Config from DHCP, PPP, or system config files */
GMainContext * context; GMainContext * context;
GMainLoop * loop;
GThread * worker;
gboolean worker_started;
}; };
static gpointer nm_device_worker (gpointer user_data);
static void nm_device_activate_schedule_stage5_ip_config_commit (NMActRequest *req); static void nm_device_activate_schedule_stage5_ip_config_commit (NMActRequest *req);
void nm_device_bring_up (NMDevice *dev);
gboolean nm_device_bring_up_wait (NMDevice *self, gboolean cancelable);
/* /*
* nm_device_test_wireless_extensions * nm_device_test_wireless_extensions
* *
@@ -132,7 +130,6 @@ nm_device_new (const char *iface,
{ {
NMDevice * dev; NMDevice * dev;
NMDeviceType type; NMDeviceType type;
nm_completion_args args;
g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (udi != NULL, NULL); g_return_val_if_fail (udi != NULL, NULL);
@@ -167,9 +164,7 @@ nm_device_new (const char *iface,
return NULL; return NULL;
} }
/* Device thread's main loop */ dev->priv->context = app_data->main_context;
dev->priv->context = g_main_context_new ();
dev->priv->loop = g_main_loop_new (dev->priv->context, FALSE);
/* Have to bring the device up before checking link status and other stuff */ /* Have to bring the device up before checking link status and other stuff */
nm_device_bring_up_wait (dev, FALSE); nm_device_bring_up_wait (dev, FALSE);
@@ -199,21 +194,7 @@ nm_device_new (const char *iface,
if (NM_DEVICE_GET_CLASS (dev)->init) if (NM_DEVICE_GET_CLASS (dev)->init)
NM_DEVICE_GET_CLASS (dev)->init (dev); NM_DEVICE_GET_CLASS (dev)->init (dev);
/* This ref should logically go in nm_device_worker, but we need the NM_DEVICE_GET_CLASS (dev)->start (dev);
ref to be taken before the worker thread is scheduled on a cpu. */
g_object_ref (G_OBJECT (dev));
dev->priv->worker = g_thread_create (nm_device_worker, dev, TRUE, NULL);
g_assert (dev->priv->worker);
/* Block until our device thread has actually had a chance to start. */
args[0] = &dev->priv->worker_started;
args[1] = (gpointer) "nm_device_init(): waiting for device's worker thread to start";
args[2] = GINT_TO_POINTER (LOG_INFO);
args[3] = GINT_TO_POINTER (0);
nm_wait_for_completion (NM_COMPLETION_TRIES_INFINITY,
G_USEC_PER_SEC / 20, nm_completion_boolean_test, NULL, args);
nm_info ("nm_device_init(): device's worker thread started, continuing.");
return dev; return dev;
} }
@@ -237,16 +218,13 @@ nm_device_init (NMDevice * self)
self->priv->app_data = NULL; self->priv->app_data = NULL;
self->priv->act_request = NULL; self->priv->act_request = NULL;
self->priv->quit_activation = FALSE; self->priv->act_source = NULL;
self->priv->system_config_data = NULL; self->priv->system_config_data = NULL;
self->priv->use_dhcp = TRUE; self->priv->use_dhcp = TRUE;
self->priv->ip4_config = NULL; self->priv->ip4_config = NULL;
self->priv->context = NULL; self->priv->context = NULL;
self->priv->loop = NULL;
self->priv->worker = NULL;
self->priv->worker_started = FALSE;
} }
static guint32 static guint32
@@ -262,36 +240,6 @@ real_start (NMDevice *dev)
} }
/*
* nm_device_worker
*
* Main thread of the device.
*
*/
static gpointer
nm_device_worker (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
g_assert (self);
NM_DEVICE_GET_CLASS (self)->start (self);
self->priv->worker_started = TRUE;
g_main_loop_run (self->priv->loop);
g_main_loop_unref (self->priv->loop);
g_main_context_unref (self->priv->context);
self->priv->loop = NULL;
self->priv->context = NULL;
g_object_unref (G_OBJECT (self));
return NULL;
}
void void
nm_device_stop (NMDevice *self) nm_device_stop (NMDevice *self)
{ {
@@ -299,14 +247,6 @@ nm_device_stop (NMDevice *self)
nm_device_deactivate (self); nm_device_deactivate (self);
nm_device_bring_down (self); nm_device_bring_down (self);
if (self->priv->loop)
g_main_loop_quit (self->priv->loop);
if (self->priv->worker)
{
g_thread_join (self->priv->worker);
self->priv->worker = NULL;
}
} }
GMainContext * GMainContext *
@@ -588,10 +528,9 @@ nm_device_set_active_link (NMDevice *self,
self->priv->link_active = link_active; self->priv->link_active = link_active;
/* Deactivate a currently active device */ /* Deactivate a currently active device */
if (!link_active && req) if (!link_active && req) {
nm_policy_schedule_device_change_check (app_data); nm_policy_schedule_device_change_check (app_data);
else if (link_active && !req) } else if (link_active && !req) {
{
NMDevice * act_dev = nm_get_active_device (app_data); NMDevice * act_dev = nm_get_active_device (app_data);
NMActRequest * act_dev_req = act_dev ? nm_device_get_act_request (act_dev) : NULL; NMActRequest * act_dev_req = act_dev ? nm_device_get_act_request (act_dev) : NULL;
@@ -651,7 +590,6 @@ nm_device_activation_start (NMActRequest *req)
nm_act_request_ref (req); nm_act_request_ref (req);
self->priv->act_request = req; self->priv->act_request = req;
self->priv->quit_activation = FALSE;
nm_info ("Activation (%s) started...", nm_device_get_iface (self)); nm_info ("Activation (%s) started...", nm_device_get_iface (self));
@@ -687,22 +625,26 @@ nm_device_activate_stage1_device_prepare (NMActRequest *req)
self = nm_act_request_get_dev (req); self = nm_act_request_get_dev (req);
g_assert (self); g_assert (self);
/* Unref and clear activation GSource to balance
* it's creation in the function that scheduled this one.
*/
if (self->priv->act_source) {
g_source_unref (self->priv->act_source);
self->priv->act_source = NULL;
}
iface = nm_device_get_iface (self); iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 1 of 5 (Device Prepare) started...", iface); nm_info ("Activation (%s) Stage 1 of 5 (Device Prepare) started...", iface);
ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, req); ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, req);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) if (ret == NM_ACT_STAGE_RETURN_POSTPONE) {
goto out; goto out;
else if (ret == NM_ACT_STAGE_RETURN_FAILURE) } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
{
nm_policy_schedule_activation_failed (req); nm_policy_schedule_activation_failed (req);
goto out; goto out;
} }
g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
if (nm_device_activation_should_cancel (self))
goto out;
nm_device_activate_schedule_stage2_device_config (req); nm_device_activate_schedule_stage2_device_config (req);
out: out:
@@ -720,7 +662,6 @@ out:
void void
nm_device_activate_schedule_stage1_device_prepare (NMActRequest *req) nm_device_activate_schedule_stage1_device_prepare (NMActRequest *req)
{ {
GSource * source = NULL;
NMDevice * self = NULL; NMDevice * self = NULL;
g_return_if_fail (req != NULL); g_return_if_fail (req != NULL);
@@ -729,12 +670,13 @@ nm_device_activate_schedule_stage1_device_prepare (NMActRequest *req)
g_assert (self); g_assert (self);
nm_act_request_set_stage (req, NM_ACT_STAGE_DEVICE_PREPARE); nm_act_request_set_stage (req, NM_ACT_STAGE_DEVICE_PREPARE);
nm_info ("Activation (%s) Stage 1 of 5 (Device Prepare) scheduled...", nm_device_get_iface (self));
source = g_idle_source_new (); self->priv->act_source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage1_device_prepare, req, NULL); g_source_set_callback (self->priv->act_source, (GSourceFunc) nm_device_activate_stage1_device_prepare, req, NULL);
g_source_attach (source, self->priv->context); g_source_attach (self->priv->act_source, self->priv->context);
g_source_unref (source);
nm_info ("Activation (%s) Stage 1 of 5 (Device Prepare) scheduled...",
nm_device_get_iface (self));
} }
static NMActStageReturn static NMActStageReturn
@@ -774,6 +716,14 @@ nm_device_activate_stage2_device_config (NMActRequest *req)
self = nm_act_request_get_dev (req); self = nm_act_request_get_dev (req);
g_assert (self); g_assert (self);
/* Unref and clear activation GSource to balance
* it's creation in the function that scheduled this one.
*/
if (self->priv->act_source) {
g_source_unref (self->priv->act_source);
self->priv->act_source = NULL;
}
iface = nm_device_get_iface (self); iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 2 of 5 (Device Configure) starting...", iface); nm_info ("Activation (%s) Stage 2 of 5 (Device Configure) starting...", iface);
@@ -781,9 +731,6 @@ nm_device_activate_stage2_device_config (NMActRequest *req)
if (!nm_device_is_up (self)) if (!nm_device_is_up (self))
nm_device_bring_up (self); nm_device_bring_up (self);
if (nm_device_activation_should_cancel (self))
goto out;
ret = NM_DEVICE_GET_CLASS (self)->act_stage2_config (self, req); ret = NM_DEVICE_GET_CLASS (self)->act_stage2_config (self, req);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out; goto out;
@@ -796,9 +743,6 @@ nm_device_activate_stage2_device_config (NMActRequest *req)
nm_info ("Activation (%s) Stage 2 of 5 (Device Configure) successful.", iface); nm_info ("Activation (%s) Stage 2 of 5 (Device Configure) successful.", iface);
if (nm_device_activation_should_cancel (self))
goto out;
nm_device_activate_schedule_stage3_ip_config_start (req); nm_device_activate_schedule_stage3_ip_config_start (req);
out: out:
@@ -816,7 +760,6 @@ out:
void void
nm_device_activate_schedule_stage2_device_config (NMActRequest *req) nm_device_activate_schedule_stage2_device_config (NMActRequest *req)
{ {
GSource * source = NULL;
NMDevice * self = NULL; NMDevice * self = NULL;
g_return_if_fail (req != NULL); g_return_if_fail (req != NULL);
@@ -826,11 +769,12 @@ nm_device_activate_schedule_stage2_device_config (NMActRequest *req)
nm_act_request_set_stage (req, NM_ACT_STAGE_DEVICE_CONFIG); nm_act_request_set_stage (req, NM_ACT_STAGE_DEVICE_CONFIG);
source = g_idle_source_new (); self->priv->act_source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage2_device_config, req, NULL); g_source_set_callback (self->priv->act_source, (GSourceFunc) nm_device_activate_stage2_device_config, req, NULL);
g_source_attach (source, self->priv->context); g_source_attach (self->priv->act_source, self->priv->context);
g_source_unref (source);
nm_info ("Activation (%s) Stage 2 of 5 (Device Configure) scheduled...", nm_device_get_iface (self)); nm_info ("Activation (%s) Stage 2 of 5 (Device Configure) scheduled...",
nm_device_get_iface (self));
} }
@@ -887,12 +831,17 @@ nm_device_activate_stage3_ip_config_start (NMActRequest *req)
self = nm_act_request_get_dev (req); self = nm_act_request_get_dev (req);
g_assert (self); g_assert (self);
/* Unref and clear activation GSource to balance
* it's creation in the function that scheduled this one.
*/
if (self->priv->act_source) {
g_source_unref (self->priv->act_source);
self->priv->act_source = NULL;
}
iface = nm_device_get_iface (self); iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 3 of 5 (IP Configure Start) started...", iface); nm_info ("Activation (%s) Stage 3 of 5 (IP Configure Start) started...", iface);
if (nm_device_activation_should_cancel (self))
goto out;
ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip_config_start (self, req); ret = NM_DEVICE_GET_CLASS (self)->act_stage3_ip_config_start (self, req);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out; goto out;
@@ -903,9 +852,6 @@ nm_device_activate_stage3_ip_config_start (NMActRequest *req)
} }
g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
if (nm_device_activation_should_cancel (self))
goto out;
nm_device_activate_schedule_stage4_ip_config_get (req); nm_device_activate_schedule_stage4_ip_config_get (req);
out: out:
@@ -922,7 +868,6 @@ out:
void void
nm_device_activate_schedule_stage3_ip_config_start (NMActRequest *req) nm_device_activate_schedule_stage3_ip_config_start (NMActRequest *req)
{ {
GSource * source = NULL;
NMDevice * self = NULL; NMDevice * self = NULL;
g_return_if_fail (req != NULL); g_return_if_fail (req != NULL);
@@ -932,11 +877,12 @@ nm_device_activate_schedule_stage3_ip_config_start (NMActRequest *req)
nm_act_request_set_stage (req, NM_ACT_STAGE_IP_CONFIG_START); nm_act_request_set_stage (req, NM_ACT_STAGE_IP_CONFIG_START);
source = g_idle_source_new (); self->priv->act_source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage3_ip_config_start, req, NULL); g_source_set_callback (self->priv->act_source, (GSourceFunc) nm_device_activate_stage3_ip_config_start, req, NULL);
g_source_attach (source, self->priv->context); g_source_attach (self->priv->act_source, self->priv->context);
g_source_unref (source);
nm_info ("Activation (%s) Stage 3 of 5 (IP Configure Start) scheduled.", nm_device_get_iface (self)); nm_info ("Activation (%s) Stage 3 of 5 (IP Configure Start) scheduled.",
nm_device_get_iface (self));
} }
@@ -1019,6 +965,7 @@ nm_device_activate_stage4_ip_config_get (NMActRequest *req)
NMDevice * self = NULL; NMDevice * self = NULL;
NMIP4Config * ip4_config = NULL; NMIP4Config * ip4_config = NULL;
NMActStageReturn ret; NMActStageReturn ret;
const char * iface = NULL;
g_return_val_if_fail (req != NULL, FALSE); g_return_val_if_fail (req != NULL, FALSE);
@@ -1028,16 +975,18 @@ nm_device_activate_stage4_ip_config_get (NMActRequest *req)
self = nm_act_request_get_dev (req); self = nm_act_request_get_dev (req);
g_assert (self); g_assert (self);
nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Get) started...", nm_device_get_iface (self)); /* Unref and clear activation GSource to balance
* it's creation in the function that scheduled this one.
*/
if (self->priv->act_source) {
g_source_unref (self->priv->act_source);
self->priv->act_source = NULL;
}
if (nm_device_activation_should_cancel (self)) iface = nm_device_get_iface (self);
goto out; nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Get) started...", iface);
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_get_ip4_config (self, req, &ip4_config); ret = NM_DEVICE_GET_CLASS (self)->act_stage4_get_ip4_config (self, req, &ip4_config);
if (nm_device_activation_should_cancel (self))
goto out;
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out; goto out;
else if (!ip4_config || (ret == NM_ACT_STAGE_RETURN_FAILURE)) else if (!ip4_config || (ret == NM_ACT_STAGE_RETURN_FAILURE))
@@ -1047,14 +996,11 @@ nm_device_activate_stage4_ip_config_get (NMActRequest *req)
} }
g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
if (nm_device_activation_should_cancel (self))
goto out;
nm_act_request_set_ip4_config (req, ip4_config); nm_act_request_set_ip4_config (req, ip4_config);
nm_device_activate_schedule_stage5_ip_config_commit (req); nm_device_activate_schedule_stage5_ip_config_commit (req);
out: out:
nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Get) complete.", nm_device_get_iface (self)); nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Get) complete.", iface);
return FALSE; return FALSE;
} }
@@ -1068,7 +1014,6 @@ out:
void void
nm_device_activate_schedule_stage4_ip_config_get (NMActRequest *req) nm_device_activate_schedule_stage4_ip_config_get (NMActRequest *req)
{ {
GSource * source = NULL;
NMDevice * self = NULL; NMDevice * self = NULL;
g_return_if_fail (req != NULL); g_return_if_fail (req != NULL);
@@ -1077,13 +1022,13 @@ nm_device_activate_schedule_stage4_ip_config_get (NMActRequest *req)
g_assert (self); g_assert (self);
nm_act_request_set_stage (req, NM_ACT_STAGE_IP_CONFIG_GET); nm_act_request_set_stage (req, NM_ACT_STAGE_IP_CONFIG_GET);
nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Get) scheduled...",
nm_device_get_iface (self));
source = g_idle_source_new (); self->priv->act_source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage4_ip_config_get, req, NULL); g_source_set_callback (self->priv->act_source, (GSourceFunc) nm_device_activate_stage4_ip_config_get, req, NULL);
g_source_attach (source, self->priv->context); g_source_attach (self->priv->act_source, self->priv->context);
g_source_unref (source);
nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Get) scheduled...",
nm_device_get_iface (self));
} }
@@ -1131,9 +1076,6 @@ nm_device_activate_stage4_ip_config_timeout (NMActRequest *req)
iface = nm_device_get_iface (self); iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Timeout) started...", iface); nm_info ("Activation (%s) Stage 4 of 5 (IP Configure Timeout) started...", iface);
if (nm_device_activation_should_cancel (self))
goto out;
ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip_config_timeout (self, req, &ip4_config); ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip_config_timeout (self, req, &ip4_config);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE) if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out; goto out;
@@ -1193,6 +1135,7 @@ nm_device_activate_stage5_ip_config_commit (NMActRequest *req)
NMData * data = NULL; NMData * data = NULL;
NMDevice * self = NULL; NMDevice * self = NULL;
NMIP4Config * ip4_config = NULL; NMIP4Config * ip4_config = NULL;
const char * iface;
g_return_val_if_fail (req != NULL, FALSE); g_return_val_if_fail (req != NULL, FALSE);
@@ -1205,15 +1148,20 @@ nm_device_activate_stage5_ip_config_commit (NMActRequest *req)
ip4_config = nm_act_request_get_ip4_config (req); ip4_config = nm_act_request_get_ip4_config (req);
g_assert (ip4_config); g_assert (ip4_config);
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) started...", /* Unref and clear activation GSource to balance
nm_device_get_iface (self)); * it's creation in the function that scheduled this one.
*/
if (self->priv->act_source) {
g_source_unref (self->priv->act_source);
self->priv->act_source = NULL;
}
if (nm_device_activation_should_cancel (self)) iface = nm_device_get_iface (self);
goto out; nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) started...",
iface);
nm_device_set_ip4_config (self, ip4_config); nm_device_set_ip4_config (self, ip4_config);
if (nm_system_device_set_from_ip4_config (self)) if (nm_system_device_set_from_ip4_config (self)) {
{
nm_device_update_ip4_address (self); nm_device_update_ip4_address (self);
nm_system_device_add_ip6_link_address (self); nm_system_device_add_ip6_link_address (self);
nm_system_restart_mdns_responder (); nm_system_restart_mdns_responder ();
@@ -1223,13 +1171,12 @@ nm_device_activate_stage5_ip_config_commit (NMActRequest *req)
if (NM_DEVICE_GET_CLASS (self)->update_link) if (NM_DEVICE_GET_CLASS (self)->update_link)
NM_DEVICE_GET_CLASS (self)->update_link (self); NM_DEVICE_GET_CLASS (self)->update_link (self);
nm_policy_schedule_activation_finish (req); nm_policy_schedule_activation_finish (req);
} } else {
else
nm_policy_schedule_activation_failed (req); nm_policy_schedule_activation_failed (req);
}
out:
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) complete.", nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) complete.",
nm_device_get_iface (self)); iface);
return FALSE; return FALSE;
} }
@@ -1242,7 +1189,6 @@ out:
static void static void
nm_device_activate_schedule_stage5_ip_config_commit (NMActRequest *req) nm_device_activate_schedule_stage5_ip_config_commit (NMActRequest *req)
{ {
GSource * source = NULL;
NMDevice * self = NULL; NMDevice * self = NULL;
g_return_if_fail (req != NULL); g_return_if_fail (req != NULL);
@@ -1252,11 +1198,12 @@ nm_device_activate_schedule_stage5_ip_config_commit (NMActRequest *req)
nm_act_request_set_stage (req, NM_ACT_STAGE_IP_CONFIG_COMMIT); nm_act_request_set_stage (req, NM_ACT_STAGE_IP_CONFIG_COMMIT);
source = g_idle_source_new (); self->priv->act_source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage5_ip_config_commit, req, NULL); g_source_set_callback (self->priv->act_source, (GSourceFunc) nm_device_activate_stage5_ip_config_commit, req, NULL);
g_source_attach (source, self->priv->context); g_source_attach (self->priv->act_source, self->priv->context);
g_source_unref (source);
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) scheduled...", nm_device_get_iface (self)); nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) scheduled...",
nm_device_get_iface (self));
} }
@@ -1271,86 +1218,6 @@ real_activation_cancel_handler (NMDevice *self,
nm_dhcp_manager_cancel_transaction (self->priv->app_data->dhcp_manager, req); nm_dhcp_manager_cancel_transaction (self->priv->app_data->dhcp_manager, req);
} }
/*
* activation_handle_cancel_helper
*
* Allow specific device types to clean up their own cancellation
*
*/
static gboolean
activation_handle_cancel_helper (NMActRequest *req)
{
NMDevice * self;
NMDeviceClass *klass;
g_assert (req);
self = nm_act_request_get_dev (req);
g_assert (self);
klass = NM_DEVICE_CLASS (g_type_class_peek (NM_TYPE_DEVICE));
if (klass->activation_cancel_handler)
klass->activation_cancel_handler (self, req);
if ((req = nm_device_get_act_request (self)))
{
self->priv->act_request = NULL;
nm_act_request_unref (req);
}
nm_schedule_state_change_signal_broadcast (self->priv->app_data);
nm_info ("Activation (%s) cancellation handled.", nm_device_get_iface (self));
return FALSE;
}
/*
* nm_device_schedule_activation_handle_cancel
*
* Schedule the activation cancel handler
*
*/
static void
nm_device_schedule_activation_handle_cancel (NMActRequest *req)
{
NMDevice * self;
NMData * data;
GSource * source;
g_return_if_fail (req != NULL);
data = nm_act_request_get_data (req);
g_assert (data);
self = nm_act_request_get_dev (req);
g_assert (self);
nm_info ("Activation (%s) cancellation handler scheduled...", nm_device_get_iface (self));
source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) activation_handle_cancel_helper, req, NULL);
g_source_set_priority (source, G_PRIORITY_HIGH_IDLE);
g_source_attach (source, self->priv->context);
g_source_unref (source);
}
static
gboolean nm_ac_test (int tries,
nm_completion_args args)
{
NMDevice * self = args[0];
g_return_val_if_fail (self != NULL, TRUE);
if (nm_device_is_activating (self))
{
if (tries % 20 == 0)
nm_info ("Activation (%s): waiting for device to cancel activation.", nm_device_get_iface (self));
return FALSE;
}
return TRUE;
}
/* /*
* nm_device_activation_cancel * nm_device_activation_cancel
@@ -1361,33 +1228,33 @@ gboolean nm_ac_test (int tries,
void void
nm_device_activation_cancel (NMDevice *self) nm_device_activation_cancel (NMDevice *self)
{ {
nm_completion_args args; NMDeviceClass *klass;
NMData * app_data;
g_return_if_fail (self != NULL); g_return_if_fail (self != NULL);
if (!nm_device_is_activating (self))
return;
g_assert (self->priv->app_data); g_assert (self->priv->app_data);
app_data = self->priv->app_data;
if (nm_device_is_activating (self)) nm_info ("Activation (%s): cancelling...", nm_device_get_iface (self));
{
NMActRequest * req = nm_device_get_act_request (self);
nm_info ("Activation (%s): cancelling...", nm_device_get_iface (self)); /* Break the activation chain */
self->priv->quit_activation = TRUE; if (self->priv->act_source) {
g_source_destroy (self->priv->act_source);
nm_device_schedule_activation_handle_cancel (req); g_source_unref (self->priv->act_source);
self->priv->act_source = NULL;
/* Spin until cancelled. Possible race conditions or deadlocks here.
* The other problem with waiting here is that we hold up dbus traffic
* that we should respond to.
*/
args[0] = self;
nm_wait_for_completion (NM_COMPLETION_TRIES_INFINITY, G_USEC_PER_SEC / 20, nm_ac_test, NULL, args);
nm_info ("Activation (%s): cancelled.", nm_device_get_iface (self));
nm_schedule_state_change_signal_broadcast (app_data);
self->priv->quit_activation = FALSE;
} }
klass = NM_DEVICE_CLASS (g_type_class_peek (NM_TYPE_DEVICE));
if (klass->activation_cancel_handler)
klass->activation_cancel_handler (self, self->priv->act_request);
nm_act_request_unref (self->priv->act_request);
self->priv->act_request = NULL;
nm_schedule_state_change_signal_broadcast (self->priv->app_data);
nm_info ("Activation (%s): cancelled.", nm_device_get_iface (self));
} }
@@ -1560,21 +1427,6 @@ nm_device_is_activated (NMDevice *dev)
} }
/*
* nm_device_activation_should_cancel
*
* Return whether or not we've been told to cancel activation
*
*/
gboolean
nm_device_activation_should_cancel (NMDevice *self)
{
g_return_val_if_fail (self != NULL, FALSE);
return (self->priv->quit_activation);
}
void void
nm_device_activation_failure_handler (NMDevice *self, nm_device_activation_failure_handler (NMDevice *self,
struct NMActRequest *req) struct NMActRequest *req)
@@ -1779,7 +1631,7 @@ nm_completion_device_is_up_test (int tries,
g_return_val_if_fail (err != NULL, TRUE); g_return_val_if_fail (err != NULL, TRUE);
*err = FALSE; *err = FALSE;
if (cancelable && nm_device_activation_should_cancel (self)) { if (cancelable /* && nm_device_activation_should_cancel (self) */) {
*err = TRUE; *err = TRUE;
return TRUE; return TRUE;
} }
@@ -1824,49 +1676,6 @@ nm_device_bring_down (NMDevice *self)
nm_device_set_up_down (self, FALSE); nm_device_set_up_down (self, FALSE);
} }
static gboolean
nm_completion_device_is_down_test (int tries,
nm_completion_args args)
{
NMDevice *self = NM_DEVICE (args[0]);
gboolean *err = args[1];
gboolean cancelable = GPOINTER_TO_INT (args[2]);
g_return_val_if_fail (self != NULL, TRUE);
g_return_val_if_fail (err != NULL, TRUE);
*err = FALSE;
if (cancelable && nm_device_activation_should_cancel (self)) {
*err = TRUE;
return TRUE;
}
if (!nm_device_is_up (self))
return TRUE;
return FALSE;
}
gboolean
nm_device_bring_down_wait (NMDevice *self,
gboolean cancelable)
{
gboolean err = FALSE;
nm_completion_args args;
g_return_val_if_fail (self != NULL, TRUE);
nm_device_bring_down (self);
args[0] = self;
args[1] = &err;
args[2] = GINT_TO_POINTER (cancelable);
nm_wait_for_completion(400, G_USEC_PER_SEC / 200, NULL,
nm_completion_device_is_down_test, args);
if (err)
nm_info ("failed to bring down device %s", self->priv->iface);
return err;
}
/* /*
* nm_device_get_system_config_data * nm_device_get_system_config_data
* *
@@ -1916,6 +1725,12 @@ nm_device_dispose (GObject *object)
self->priv->act_request = NULL; self->priv->act_request = NULL;
} }
if (self->priv->act_source) {
g_source_destroy (self->priv->act_source);
g_source_unref (self->priv->act_source);
self->priv->act_source = NULL;
}
/* Chain up to the parent class */ /* Chain up to the parent class */
klass = NM_DEVICE_CLASS (g_type_class_peek (NM_TYPE_DEVICE)); klass = NM_DEVICE_CLASS (g_type_class_peek (NM_TYPE_DEVICE));
parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));

View File

@@ -165,12 +165,7 @@ NMIP4Config * nm_device_get_ip4_config (NMDevice *dev);
void nm_device_set_ip4_config (NMDevice *dev, void nm_device_set_ip4_config (NMDevice *dev,
NMIP4Config *config); NMIP4Config *config);
void nm_device_bring_up (NMDevice *dev);
gboolean nm_device_bring_up_wait (NMDevice *self,
gboolean cancelable);
void nm_device_bring_down (NMDevice *dev); void nm_device_bring_down (NMDevice *dev);
gboolean nm_device_bring_down_wait (NMDevice *self,
gboolean cancelable);
gboolean nm_device_is_up (NMDevice *dev); gboolean nm_device_is_up (NMDevice *dev);
void * nm_device_get_system_config_data (NMDevice *dev); void * nm_device_get_system_config_data (NMDevice *dev);
@@ -196,7 +191,6 @@ void nm_device_deactivate (NMDevice *dev);
gboolean nm_device_deactivate_quickly (NMDevice *dev); gboolean nm_device_deactivate_quickly (NMDevice *dev);
gboolean nm_device_is_activating (NMDevice *dev); gboolean nm_device_is_activating (NMDevice *dev);
void nm_device_activation_cancel (NMDevice *dev); void nm_device_activation_cancel (NMDevice *dev);
gboolean nm_device_activation_should_cancel (NMDevice *self);
void nm_device_activation_failure_handler (NMDevice *dev, void nm_device_activation_failure_handler (NMDevice *dev,
struct NMActRequest *req); struct NMActRequest *req);