From aa5013cf2dababefb75c1473845387c71a961498 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 11 Feb 2013 11:15:45 -0600 Subject: [PATCH] core: fix duplicating (not removing) active connections This is a regression introduced by reworked active connections tracking: 7258dd270f01d7956a2a61f4378a0a28b29db2d0 core: add the NM_ACTIVE_CONNECTION_STATE_DEACTIVATED state 59420add04de26ed9367feb966211a6446626803 core: track active connections directly in the manager Because nm-manager.c:active_connection_state_changed() postpones active connection removal to an idle handler (to be able to receive last property change notifications), we also need to ensure that NM_ACTIVE_CONNECTION_STATE_DEACTIVATED state is not changed again in the meantime in nm-activation-request.c:device_state_changed(). After the NMActRequest was deactivated (which is a terminal state) it was still listening to state changes of its child NMDevice which could be starting a new activation request. Thus the new activation's NMDevice state would cause the old activation request's state to change from DEACTIVATED. To fix this stop listening to the child NMDevice when DEACTIVATED becuase there's no point to doing so anyway. Reproducer: Just activate already active connection by clicking it in nm-applet or run 'nmcli con up id ' several times, and then check active connections with 'nmcli c s'. --- src/nm-activation-request.c | 8 ++++++++ src/nm-active-connection.c | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c index 88504ce0dd..76949cf279 100644 --- a/src/nm-activation-request.c +++ b/src/nm-activation-request.c @@ -297,6 +297,7 @@ nm_act_request_add_share_rule (NMActRequest *req, static void device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self) { + NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self); NMActiveConnectionState ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN; /* Set NMActiveConnection state based on the device's state */ @@ -318,6 +319,13 @@ device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self) case NM_DEVICE_STATE_FAILED: case NM_DEVICE_STATE_DISCONNECTED: ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATED; + + /* No longer need to pay attention to device state */ + if (priv->device && priv->device_state_id) { + g_signal_handler_disconnect (priv->device, priv->device_state_id); + priv->device_state_id = 0; + } + g_clear_object (&priv->device); break; default: break; diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index 15b4b48553..6e3a5da63c 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -101,6 +101,10 @@ nm_active_connection_set_state (NMActiveConnection *self, if (priv->state == new_state) return; + /* DEACTIVATED is a terminal state */ + if (priv->state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) + g_return_if_fail (new_state != NM_ACTIVE_CONNECTION_STATE_DEACTIVATED); + old_state = priv->state; priv->state = new_state; g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_STATE); @@ -110,6 +114,12 @@ nm_active_connection_set_state (NMActiveConnection *self, nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (priv->connection), (guint64) time (NULL), TRUE); } + + if (priv->state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { + /* Device is no longer relevant when deactivated */ + g_clear_object (&priv->device); + g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEVICES); + } } const char *