diff options
author | Thomas Haller <thaller@redhat.com> | 2020-01-14 13:58:20 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2020-01-16 12:44:56 +0100 |
commit | b572c0542a0ab5f39df44fdbaa93bc7d6b7a3c9e (patch) | |
tree | d0c3b4befbd47cdf6bc5b4fa33fc0b6fd08aa5f1 | |
parent | a2fd2ab55d33e0beaf0ef4cdab3e1b0539a5de59 (diff) | |
download | NetworkManager-b572c0542a0ab5f39df44fdbaa93bc7d6b7a3c9e.tar.gz |
libnm: keep context-busy-watcher of NMClient alive for one more idle round
The context-busy-watch has two purposes:
1) it allows the user to watch whether the NMClient still has pending
GSource'es attached to the GMainContext.
2) thereby, it also keeps the inner GMainContext integrated into the
caller's (in case of synchronous initialization of NMClient).
Especially for 2), we must not get this wrong. Otherwise, we might
un-integrate the inner GMainContext too early and it will be leaked
indefinitely (because the user has no means to access or iterate it).
To be extra careful, extend the lifetime of the context-busy-watcher
for one more idle invocation. Theoretically, this should not be necessary,
but it's not clear whether something else is still pending.
The downside of that extra safety is that it is probably unnecessary in
practice. And in case where it is necessary, it hides an actual
issue, making it harder to notice and fix it.
-rw-r--r-- | libnm/nm-client.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/libnm/nm-client.c b/libnm/nm-client.c index b27890a831..89f4a02827 100644 --- a/libnm/nm-client.c +++ b/libnm/nm-client.c @@ -7617,6 +7617,32 @@ dispose (GObject *object) nm_clear_pointer (&priv->udev, udev_unref); + if ( priv->context_busy_watcher + && priv->dbus_context) { + GSource *cleanup_source; + + /* Technically, we cancelled all pending actions (and these actions keep + * the context_busy_watcher object alive). Also, we passed + * no destroy notify to g_dbus_connection_signal_subscribe(). + * That means, there should be no other unaccounted GSource'es left. + * + * However, we really need to be sure that the context_busy_watcher's + * lifetime matches the time that the context is busy. That is especially + * important with synchronous initialization, where the context-busy-watcher + * keeps the inner GMainContext integrated in the caller's. + * We must not g_source_destroy() that integration too early. + * + * So to be really sure all this is given, always schedule one last + * cleanup idle action with low priority. This should be the last + * thing related to this instance that keeps the context busy. */ + cleanup_source = nm_g_idle_source_new (G_PRIORITY_LOW + 10, + nm_source_func_unref_gobject, + g_steal_pointer (&priv->context_busy_watcher), + NULL); + g_source_attach (cleanup_source, priv->dbus_context); + g_source_unref (cleanup_source); + } + nm_clear_pointer (&priv->dbus_context, g_main_context_unref); nm_clear_pointer (&priv->main_context, g_main_context_unref); |