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>
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;
if (FD_ISSET(sk, &fs))
return RET_SUCCESS;
if (nm_device_activation_should_cancel (dev))
return RET_CEASED;
gettimeofday (&now, NULL);
};
return RET_TIMEOUT;
@ -262,10 +260,6 @@ gboolean get_autoip (NMDevice *dev, struct in_addr *out_ip)
struct timeval timeout;
int err;
/* Make sure we haven't been told to quit */
if (nm_device_activation_should_cancel (dev))
goto out;
if (nprobes < PROBE_NUM)
{
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)
{
NMActRequest * req = args[0];
NMDevice * dev = args[1];
if (state_is_bound (nm_act_request_get_dhcp_state (req)))
return TRUE;
if (nm_device_activation_should_cancel (dev))
return TRUE;
return FALSE;
}
@ -618,8 +615,6 @@ nm_dhcp_manager_get_ip4_config (NMDHCPManager *manager,
args[1] = dev;
nm_wait_for_completion (30, G_USEC_PER_SEC / 10,
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))) {
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 */
if (self->priv->supplicant.con_timeout != NULL) {
g_source_destroy (self->priv->supplicant.con_timeout);
g_source_unref (self->priv->supplicant.con_timeout);
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
remove_supplicant_timeouts (NMDevice80211Wireless *self)
{
@ -2912,7 +2942,6 @@ real_act_stage2_config (NMDevice *dev,
const char * iface = nm_device_get_iface (dev);
gboolean ask_user = FALSE;
NMSupplicantConfig * config = NULL;
GMainContext * context;
gulong id = 0;
g_assert (ap);
@ -2932,9 +2961,6 @@ real_act_stage2_config (NMDevice *dev,
goto out;
}
if (nm_device_activation_should_cancel (NM_DEVICE (self)))
goto out;
/* Hook up error signal handler to capture association errors */
id = g_signal_connect (G_OBJECT (self->priv->supplicant.iface),
"connection-error",
@ -2948,19 +2974,8 @@ real_act_stage2_config (NMDevice *dev,
goto out;
}
/* 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) {
nm_warning ("Activation (%s/wireless): couldn't start supplicant "
"timeout timer.", iface);
if (!start_supplicant_connection_timeout (self))
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 */
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)
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);
}
static gboolean
link_activated_helper (NMDevice8023Ethernet *self)
{
nm_device_set_active_link (NM_DEVICE (self), TRUE);
return FALSE;
}
static void
nm_device_802_3_ethernet_link_activated (NmNetlinkMonitor *monitor,
GObject *obj,
NMDevice8023Ethernet *self)
{
NMDevice * dev = NM_DEVICE (self);
/* Make sure signal is for us */
if (NM_DEVICE (self) != NM_DEVICE (obj))
if (dev != NM_DEVICE (obj))
return;
if (!nm_device_has_active_link (NM_DEVICE (self)))
{
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);
}
nm_device_set_active_link (dev, TRUE);
}
static gboolean
link_deactivated_helper (NMDevice8023Ethernet *self)
{
nm_device_set_active_link (NM_DEVICE (self), FALSE);
return FALSE;
}
static void
nm_device_802_3_ethernet_link_deactivated (NmNetlinkMonitor *monitor,
GObject *obj,
NMDevice8023Ethernet *self)
{
NMDevice * dev = NM_DEVICE (self);
/* Make sure signal is for us */
if (NM_DEVICE (self) != NM_DEVICE (obj))
if (dev != NM_DEVICE (obj))
return;
if (nm_device_has_active_link (NM_DEVICE (self)))
{
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);
}
nm_device_set_active_link (dev, FALSE);
}
static gboolean
@ -316,6 +292,22 @@ real_get_generic_capabilities (NMDevice *dev)
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
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->start = real_start;
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));
}

View file

@ -58,7 +58,7 @@ struct _NMDevicePrivate
NMData * app_data;
NMActRequest * act_request;
gboolean quit_activation;
GSource * act_source;
/* IP configuration info */
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 */
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);
void nm_device_bring_up (NMDevice *dev);
gboolean nm_device_bring_up_wait (NMDevice *self, gboolean cancelable);
/*
* nm_device_test_wireless_extensions
*
@ -132,7 +130,6 @@ nm_device_new (const char *iface,
{
NMDevice * dev;
NMDeviceType type;
nm_completion_args args;
g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (udi != NULL, NULL);
@ -167,9 +164,7 @@ nm_device_new (const char *iface,
return NULL;
}
/* Device thread's main loop */
dev->priv->context = g_main_context_new ();
dev->priv->loop = g_main_loop_new (dev->priv->context, FALSE);
dev->priv->context = app_data->main_context;
/* Have to bring the device up before checking link status and other stuff */
nm_device_bring_up_wait (dev, FALSE);
@ -199,21 +194,7 @@ nm_device_new (const char *iface,
if (NM_DEVICE_GET_CLASS (dev)->init)
NM_DEVICE_GET_CLASS (dev)->init (dev);
/* This ref should logically go in nm_device_worker, but we need the
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.");
NM_DEVICE_GET_CLASS (dev)->start (dev);
return dev;
}
@ -237,16 +218,13 @@ nm_device_init (NMDevice * self)
self->priv->app_data = NULL;
self->priv->act_request = NULL;
self->priv->quit_activation = FALSE;
self->priv->act_source = NULL;
self->priv->system_config_data = NULL;
self->priv->use_dhcp = TRUE;
self->priv->ip4_config = NULL;
self->priv->context = NULL;
self->priv->loop = NULL;
self->priv->worker = NULL;
self->priv->worker_started = FALSE;
}
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
nm_device_stop (NMDevice *self)
{
@ -299,14 +247,6 @@ nm_device_stop (NMDevice *self)
nm_device_deactivate (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 *
@ -588,10 +528,9 @@ nm_device_set_active_link (NMDevice *self,
self->priv->link_active = link_active;
/* Deactivate a currently active device */
if (!link_active && req)
if (!link_active && req) {
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);
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);
self->priv->act_request = req;
self->priv->quit_activation = FALSE;
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);
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);
nm_info ("Activation (%s) Stage 1 of 5 (Device Prepare) started...", iface);
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;
else if (ret == NM_ACT_STAGE_RETURN_FAILURE)
{
} else if (ret == NM_ACT_STAGE_RETURN_FAILURE) {
nm_policy_schedule_activation_failed (req);
goto out;
}
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);
out:
@ -720,7 +662,6 @@ out:
void
nm_device_activate_schedule_stage1_device_prepare (NMActRequest *req)
{
GSource * source = NULL;
NMDevice * self = NULL;
g_return_if_fail (req != NULL);
@ -729,12 +670,13 @@ nm_device_activate_schedule_stage1_device_prepare (NMActRequest *req)
g_assert (self);
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 ();
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage1_device_prepare, req, NULL);
g_source_attach (source, self->priv->context);
g_source_unref (source);
self->priv->act_source = g_idle_source_new ();
g_source_set_callback (self->priv->act_source, (GSourceFunc) nm_device_activate_stage1_device_prepare, req, NULL);
g_source_attach (self->priv->act_source, self->priv->context);
nm_info ("Activation (%s) Stage 1 of 5 (Device Prepare) scheduled...",
nm_device_get_iface (self));
}
static NMActStageReturn
@ -774,6 +716,14 @@ nm_device_activate_stage2_device_config (NMActRequest *req)
self = nm_act_request_get_dev (req);
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);
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))
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);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
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);
if (nm_device_activation_should_cancel (self))
goto out;
nm_device_activate_schedule_stage3_ip_config_start (req);
out:
@ -816,7 +760,6 @@ out:
void
nm_device_activate_schedule_stage2_device_config (NMActRequest *req)
{
GSource * source = NULL;
NMDevice * self = 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);
source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage2_device_config, req, NULL);
g_source_attach (source, self->priv->context);
g_source_unref (source);
nm_info ("Activation (%s) Stage 2 of 5 (Device Configure) scheduled...", nm_device_get_iface (self));
self->priv->act_source = g_idle_source_new ();
g_source_set_callback (self->priv->act_source, (GSourceFunc) nm_device_activate_stage2_device_config, req, NULL);
g_source_attach (self->priv->act_source, self->priv->context);
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);
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);
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);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out;
@ -903,9 +852,6 @@ nm_device_activate_stage3_ip_config_start (NMActRequest *req)
}
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);
out:
@ -922,7 +868,6 @@ out:
void
nm_device_activate_schedule_stage3_ip_config_start (NMActRequest *req)
{
GSource * source = NULL;
NMDevice * self = 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);
source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage3_ip_config_start, req, NULL);
g_source_attach (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));
self->priv->act_source = g_idle_source_new ();
g_source_set_callback (self->priv->act_source, (GSourceFunc) nm_device_activate_stage3_ip_config_start, req, NULL);
g_source_attach (self->priv->act_source, self->priv->context);
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;
NMIP4Config * ip4_config = NULL;
NMActStageReturn ret;
const char * iface = NULL;
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);
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))
goto out;
iface = nm_device_get_iface (self);
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);
if (nm_device_activation_should_cancel (self))
goto out;
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out;
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);
if (nm_device_activation_should_cancel (self))
goto out;
nm_act_request_set_ip4_config (req, ip4_config);
nm_device_activate_schedule_stage5_ip_config_commit (req);
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;
}
@ -1068,7 +1014,6 @@ out:
void
nm_device_activate_schedule_stage4_ip_config_get (NMActRequest *req)
{
GSource * source = NULL;
NMDevice * self = NULL;
g_return_if_fail (req != NULL);
@ -1077,13 +1022,13 @@ nm_device_activate_schedule_stage4_ip_config_get (NMActRequest *req)
g_assert (self);
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 ();
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage4_ip_config_get, req, NULL);
g_source_attach (source, self->priv->context);
g_source_unref (source);
self->priv->act_source = g_idle_source_new ();
g_source_set_callback (self->priv->act_source, (GSourceFunc) nm_device_activate_stage4_ip_config_get, req, NULL);
g_source_attach (self->priv->act_source, self->priv->context);
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);
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);
if (ret == NM_ACT_STAGE_RETURN_POSTPONE)
goto out;
@ -1193,6 +1135,7 @@ nm_device_activate_stage5_ip_config_commit (NMActRequest *req)
NMData * data = NULL;
NMDevice * self = NULL;
NMIP4Config * ip4_config = NULL;
const char * iface;
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);
g_assert (ip4_config);
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) 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))
goto out;
iface = nm_device_get_iface (self);
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) started...",
iface);
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_system_device_add_ip6_link_address (self);
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)
NM_DEVICE_GET_CLASS (self)->update_link (self);
nm_policy_schedule_activation_finish (req);
}
else
} else {
nm_policy_schedule_activation_failed (req);
}
out:
nm_info ("Activation (%s) Stage 5 of 5 (IP Configure Commit) complete.",
nm_device_get_iface (self));
iface);
return FALSE;
}
@ -1242,7 +1189,6 @@ out:
static void
nm_device_activate_schedule_stage5_ip_config_commit (NMActRequest *req)
{
GSource * source = NULL;
NMDevice * self = 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);
source = g_idle_source_new ();
g_source_set_callback (source, (GSourceFunc) nm_device_activate_stage5_ip_config_commit, req, NULL);
g_source_attach (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));
self->priv->act_source = g_idle_source_new ();
g_source_set_callback (self->priv->act_source, (GSourceFunc) nm_device_activate_stage5_ip_config_commit, req, NULL);
g_source_attach (self->priv->act_source, self->priv->context);
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);
}
/*
* 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
@ -1361,33 +1228,33 @@ gboolean nm_ac_test (int tries,
void
nm_device_activation_cancel (NMDevice *self)
{
nm_completion_args args;
NMData * app_data;
NMDeviceClass *klass;
g_return_if_fail (self != NULL);
if (!nm_device_is_activating (self))
return;
g_assert (self->priv->app_data);
app_data = self->priv->app_data;
if (nm_device_is_activating (self))
{
NMActRequest * req = nm_device_get_act_request (self);
nm_info ("Activation (%s): cancelling...", nm_device_get_iface (self));
nm_info ("Activation (%s): cancelling...", nm_device_get_iface (self));
self->priv->quit_activation = TRUE;
nm_device_schedule_activation_handle_cancel (req);
/* 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;
/* Break the activation chain */
if (self->priv->act_source) {
g_source_destroy (self->priv->act_source);
g_source_unref (self->priv->act_source);
self->priv->act_source = NULL;
}
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
nm_device_activation_failure_handler (NMDevice *self,
struct NMActRequest *req)
@ -1779,7 +1631,7 @@ nm_completion_device_is_up_test (int tries,
g_return_val_if_fail (err != NULL, TRUE);
*err = FALSE;
if (cancelable && nm_device_activation_should_cancel (self)) {
if (cancelable /* && nm_device_activation_should_cancel (self) */) {
*err = TRUE;
return TRUE;
}
@ -1824,49 +1676,6 @@ nm_device_bring_down (NMDevice *self)
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
*
@ -1916,6 +1725,12 @@ nm_device_dispose (GObject *object)
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 */
klass = NM_DEVICE_CLASS (g_type_class_peek (NM_TYPE_DEVICE));
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,
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);
gboolean nm_device_bring_down_wait (NMDevice *self,
gboolean cancelable);
gboolean nm_device_is_up (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_is_activating (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,
struct NMActRequest *req);