mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-29 04:30:09 +01:00
manager: disconnect devices before unmanaging them on suspend/sleep
So that dispatcher scripts are run and other applications notified of
the change in connectivity.
https://bugzilla.redhat.com/show_bug.cgi?id=1330694
https://bugzilla.gnome.org/show_bug.cgi?id=748531
(cherry picked from commit 81ea812362)
This commit is contained in:
parent
69c1395317
commit
c81887ae6c
1 changed files with 115 additions and 2 deletions
117
src/nm-manager.c
117
src/nm-manager.c
|
|
@ -79,6 +79,9 @@ static gboolean find_master (NMManager *self,
|
|||
static void nm_manager_update_state (NMManager *manager);
|
||||
|
||||
static void connection_changed (NMManager *self, NMConnection *connection);
|
||||
static void device_sleep_cb (NMDevice *device,
|
||||
GParamSpec *pspec,
|
||||
NMManager *self);
|
||||
|
||||
#define TAG_ACTIVE_CONNETION_ADD_AND_ACTIVATE "act-con-add-and-activate"
|
||||
|
||||
|
|
@ -129,6 +132,7 @@ typedef struct {
|
|||
NMSleepMonitor *sleep_monitor;
|
||||
|
||||
GSList *auth_chains;
|
||||
GHashTable *sleep_devices;
|
||||
|
||||
/* Firmware dir monitor */
|
||||
GFileMonitor *fw_monitor;
|
||||
|
|
@ -3862,6 +3866,98 @@ device_is_wake_on_lan (NMDevice *device)
|
|||
return nm_platform_link_get_wake_on_lan (NM_PLATFORM_GET, nm_device_get_ip_ifindex (device));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sleep_devices_add (NMManager *self, NMDevice *device, gboolean suspending)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
NMSleepMonitorInhibitorHandle *handle = NULL;
|
||||
|
||||
if (g_hash_table_lookup_extended (priv->sleep_devices, device, NULL, (gpointer *) &handle)) {
|
||||
if (suspending) {
|
||||
/* if we are suspending, always insert a new handle in sleep_devices.
|
||||
* Even if we had an old handle, it might be stale by now. */
|
||||
g_hash_table_insert (priv->sleep_devices, device,
|
||||
nm_sleep_monitor_inhibit_take (priv->sleep_monitor));
|
||||
if (handle)
|
||||
nm_sleep_monitor_inhibit_release (priv->sleep_monitor, handle);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_hash_table_insert (priv->sleep_devices,
|
||||
g_object_ref (device),
|
||||
suspending
|
||||
? nm_sleep_monitor_inhibit_take (priv->sleep_monitor)
|
||||
: NULL);
|
||||
g_signal_connect (device, "notify::" NM_DEVICE_STATE, (GCallback) device_sleep_cb, self);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
sleep_devices_remove (NMManager *self, NMDevice *device)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
NMSleepMonitorInhibitorHandle *handle;
|
||||
|
||||
if (!g_hash_table_lookup_extended (priv->sleep_devices, device, NULL, (gpointer *) &handle))
|
||||
return FALSE;
|
||||
|
||||
if (handle)
|
||||
nm_sleep_monitor_inhibit_release (priv->sleep_monitor, handle);
|
||||
|
||||
/* Remove device from hash */
|
||||
g_signal_handlers_disconnect_by_func (device, device_sleep_cb, self);
|
||||
g_hash_table_remove (priv->sleep_devices, device);
|
||||
g_object_unref (device);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
sleep_devices_clear (NMManager *self)
|
||||
{
|
||||
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
NMDevice *device;
|
||||
NMSleepMonitorInhibitorHandle *handle;
|
||||
GHashTableIter iter;
|
||||
|
||||
if (!priv->sleep_devices)
|
||||
return;
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->sleep_devices);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &device, (gpointer *) &handle)) {
|
||||
g_signal_handlers_disconnect_by_func (device, device_sleep_cb, self);
|
||||
if (handle)
|
||||
nm_sleep_monitor_inhibit_release (priv->sleep_monitor, handle);
|
||||
g_object_unref (device);
|
||||
g_hash_table_iter_remove (&iter);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
device_sleep_cb (NMDevice *device,
|
||||
GParamSpec *pspec,
|
||||
NMManager *self)
|
||||
{
|
||||
switch (nm_device_get_state (device)) {
|
||||
case NM_DEVICE_STATE_DISCONNECTED:
|
||||
_LOGD (LOGD_SUSPEND, "sleep: unmanaging device %s", nm_device_get_ip_iface (device));
|
||||
nm_device_set_unmanaged_by_flags_queue (device,
|
||||
NM_UNMANAGED_SLEEPING,
|
||||
TRUE,
|
||||
NM_DEVICE_STATE_REASON_SLEEPING);
|
||||
break;
|
||||
case NM_DEVICE_STATE_UNMANAGED:
|
||||
_LOGD (LOGD_SUSPEND, "sleep: device %s is ready", nm_device_get_ip_iface (device));
|
||||
|
||||
if (!sleep_devices_remove (self, device))
|
||||
g_return_if_reached ();
|
||||
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_sleep_wake (NMManager *self, gboolean sleeping_changed)
|
||||
{
|
||||
|
|
@ -3885,15 +3981,28 @@ do_sleep_wake (NMManager *self, gboolean sleeping_changed)
|
|||
if (nm_device_is_software (device))
|
||||
continue;
|
||||
/* Wake-on-LAN devices will be taken down post-suspend rather than pre- */
|
||||
if (suspending && device_is_wake_on_lan (device))
|
||||
if (suspending && device_is_wake_on_lan (device)) {
|
||||
_LOGD (LOGD_SUSPEND, "sleep: device %s has wake-on-lan, skipping",
|
||||
nm_device_get_ip_iface (device));
|
||||
continue;
|
||||
}
|
||||
|
||||
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING);
|
||||
if (nm_device_is_activating (device) ||
|
||||
nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) {
|
||||
_LOGD (LOGD_SUSPEND, "sleep: wait disconnection of device %s",
|
||||
nm_device_get_ip_iface (device));
|
||||
|
||||
if (sleep_devices_add (self, device, suspending))
|
||||
nm_device_queue_state (device, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_SLEEPING);
|
||||
} else {
|
||||
nm_device_set_unmanaged_by_flags (device, NM_UNMANAGED_SLEEPING, TRUE, NM_DEVICE_STATE_REASON_SLEEPING);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_LOGI (LOGD_SUSPEND, "%s...", waking_from_suspend ? "waking up" : "re-enabling");
|
||||
|
||||
if (waking_from_suspend) {
|
||||
sleep_devices_clear (self);
|
||||
/* Belatedly take down Wake-on-LAN devices; ideally we wouldn't have to do this
|
||||
* but for now it's the only way to make sure we re-check their connectivity.
|
||||
*/
|
||||
|
|
@ -5297,6 +5406,7 @@ nm_manager_init (NMManager *self)
|
|||
priv->timestamp_update_id = g_timeout_add_seconds (300, (GSourceFunc) periodic_update_active_connection_timestamps, self);
|
||||
|
||||
priv->metered = NM_METERED_UNKNOWN;
|
||||
priv->sleep_devices = g_hash_table_new (g_direct_hash, g_direct_equal);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -5520,6 +5630,9 @@ dispose (GObject *object)
|
|||
}
|
||||
_set_prop_filter (manager, NULL);
|
||||
|
||||
sleep_devices_clear (manager);
|
||||
g_clear_pointer (&priv->sleep_devices, g_hash_table_unref);
|
||||
|
||||
if (priv->sleep_monitor) {
|
||||
g_signal_handlers_disconnect_by_func (priv->sleep_monitor, sleeping_cb, manager);
|
||||
g_clear_object (&priv->sleep_monitor);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue