From c98c7a486ce69a6c53ded1ab7a0908f1dd1f3120 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 1 Oct 2015 16:41:09 +0200 Subject: macros: add nm_clear_g_signal_handler() helper --- include/nm-macros-internal.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/nm-macros-internal.h b/include/nm-macros-internal.h index 7ae08bf727..4ee5499f22 100644 --- a/include/nm-macros-internal.h +++ b/include/nm-macros-internal.h @@ -198,6 +198,19 @@ nm_clear_g_source (guint *id) return FALSE; } +static inline gboolean +nm_clear_g_signal_handler (gpointer self, guint *id) +{ + g_return_val_if_fail (G_IS_OBJECT (self), FALSE); + + if (id && *id) { + g_signal_handler_disconnect (self, *id); + *id = 0; + return TRUE; + } + return FALSE; +} + /*****************************************************************************/ /* Determine whether @x is a power of two (@x being an integer type). -- cgit v1.2.3 From e427d32ec3a12071cb9e5b61433bd65ff4a89682 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 1 Oct 2015 16:43:06 +0200 Subject: device: use nm_clear_g_signal_handler() to clear master-ready signal handler --- src/devices/nm-device.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index a6808bdee5..beba09b2f7 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -2876,10 +2876,7 @@ master_ready_cb (NMActiveConnection *active, _LOGD (LOGD_DEVICE, "master connection ready; master device %s", nm_device_get_iface (priv->master)); - if (priv->master_ready_id) { - g_signal_handler_disconnect (active, priv->master_ready_id); - priv->master_ready_id = 0; - } + nm_clear_g_signal_handler (active, &priv->master_ready_id); nm_device_activate_schedule_stage2_device_config (self); } @@ -6184,10 +6181,7 @@ clear_act_request (NMDevice *self) nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE); - if (priv->master_ready_id) { - g_signal_handler_disconnect (priv->act_request, priv->master_ready_id); - priv->master_ready_id = 0; - } + nm_clear_g_signal_handler (priv->act_request, &priv->master_ready_id); g_clear_object (&priv->act_request); g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION); -- cgit v1.2.3 From 85ac903bb8010409c4010ba09c621780b385b9b5 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Thu, 1 Oct 2015 16:48:32 +0200 Subject: device: fix activating slave device when stage1 delays action When activating for example a team device which is to be enslaved to a bridge, nm_device_activate_stage1_device_prepare() will postpone stage 2. In that case, we didn't register the "master-ready" of the team device and thus never progressed the slave from stage2. Reproduce: # nmcli connection delete t-br0 # nmcli connection delete t-team0 nmcli connection add type bridge con-name t-br0 autoconnect no ifname i-br0 ip4 192.168.177.100/24 gw4 192.168.177.1 nmcli connection add type team con-name t-team0 autoconnect no ifname i-team0 nmcli connection modify id t-team0 connection.master i-br0 connection.slave-type bridge nmcli connection up t-team0 --- src/devices/nm-device.c | 63 +++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index beba09b2f7..b15515b790 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -335,6 +335,7 @@ typedef struct { /* master interface for bridge/bond/team slave */ NMDevice * master; gboolean enslaved; + gboolean master_ready_handled; guint master_ready_id; /* slave management */ @@ -2855,19 +2856,22 @@ get_ip_config_may_fail (NMDevice *self, int family) } static void -master_ready_cb (NMActiveConnection *active, - GParamSpec *pspec, - NMDevice *self) +master_ready (NMDevice *self, + NMActiveConnection *active) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActiveConnection *master; - g_assert (priv->state == NM_DEVICE_STATE_PREPARE); + g_return_if_fail (priv->state == NM_DEVICE_STATE_PREPARE); + g_return_if_fail (!priv->master_ready_handled); /* Notify a master device that it has a new slave */ - g_assert (nm_active_connection_get_master_ready (active)); + g_return_if_fail (nm_active_connection_get_master_ready (active)); master = nm_active_connection_get_master (active); + priv->master_ready_handled = TRUE; + nm_clear_g_signal_handler (active, &priv->master_ready_id); + priv->master = g_object_ref (nm_active_connection_get_device (master)); nm_device_master_add_slave (priv->master, self, @@ -2876,8 +2880,14 @@ master_ready_cb (NMActiveConnection *active, _LOGD (LOGD_DEVICE, "master connection ready; master device %s", nm_device_get_iface (priv->master)); - nm_clear_g_signal_handler (active, &priv->master_ready_id); +} +static void +master_ready_cb (NMActiveConnection *active, + GParamSpec *pspec, + NMDevice *self) +{ + master_ready (self, active); nm_device_activate_schedule_stage2_device_config (self); } @@ -2925,23 +2935,7 @@ nm_device_activate_stage1_device_prepare (gpointer user_data) g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); } - if (nm_active_connection_get_master (active)) { - /* If the master connection is ready for slaves, attach ourselves */ - if (nm_active_connection_get_master_ready (active)) - master_ready_cb (active, NULL, self); - else { - _LOGD (LOGD_DEVICE, "waiting for master connection to become ready"); - - /* Attach a signal handler and wait for the master connection to begin activating */ - g_assert (priv->master_ready_id == 0); - priv->master_ready_id = g_signal_connect (active, - "notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY, - (GCallback) master_ready_cb, - self); - /* Postpone */ - } - } else - nm_device_activate_schedule_stage2_device_config (self); + nm_device_activate_schedule_stage2_device_config (self); out: _LOGD (LOGD_DEVICE, "Activation: Stage 1 of 5 (Device Prepare) complete."); @@ -2995,6 +2989,28 @@ nm_device_activate_stage2_device_config (gpointer user_data) NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request); GSList *iter; + if (!priv->master_ready_handled) { + if (!nm_active_connection_get_master (active)) + priv->master_ready_handled = TRUE; + else { + /* If the master connection is ready for slaves, attach ourselves */ + if (nm_active_connection_get_master_ready (active)) + master_ready (self, active); + else { + _LOGD (LOGD_DEVICE, "waiting for master connection to become ready"); + + if (priv->master_ready_id == 0) { + priv->master_ready_id = g_signal_connect (active, + "notify::" NM_ACTIVE_CONNECTION_INT_MASTER_READY, + (GCallback) master_ready_cb, + self); + } + /* Postpone */ + return FALSE; + } + } + } + /* Clear the activation source ID now that this stage has run */ activation_source_clear (self, FALSE, 0); @@ -6181,6 +6197,7 @@ clear_act_request (NMDevice *self) nm_active_connection_set_default (NM_ACTIVE_CONNECTION (priv->act_request), FALSE); + priv->master_ready_handled = FALSE; nm_clear_g_signal_handler (priv->act_request, &priv->master_ready_id); g_clear_object (&priv->act_request); -- cgit v1.2.3