core: fix duplicating (not removing) active connections
This is a regression introduced by reworked active connections tracking:7258dd270f
core: add the NM_ACTIVE_CONNECTION_STATE_DEACTIVATED state59420add04
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 <connnection name>' several times, and then check active connections with 'nmcli c s'.
This commit is contained in:
@@ -297,6 +297,7 @@ nm_act_request_add_share_rule (NMActRequest *req,
|
|||||||
static void
|
static void
|
||||||
device_state_changed (NMDevice *device, GParamSpec *pspec, NMActRequest *self)
|
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;
|
NMActiveConnectionState ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
|
||||||
|
|
||||||
/* Set NMActiveConnection state based on the device's state */
|
/* 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_FAILED:
|
||||||
case NM_DEVICE_STATE_DISCONNECTED:
|
case NM_DEVICE_STATE_DISCONNECTED:
|
||||||
ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATED;
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@@ -101,6 +101,10 @@ nm_active_connection_set_state (NMActiveConnection *self,
|
|||||||
if (priv->state == new_state)
|
if (priv->state == new_state)
|
||||||
return;
|
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;
|
old_state = priv->state;
|
||||||
priv->state = new_state;
|
priv->state = new_state;
|
||||||
g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_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),
|
nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (priv->connection),
|
||||||
(guint64) time (NULL), TRUE);
|
(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 *
|
const char *
|
||||||
|
Reference in New Issue
Block a user