summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-01-20 11:09:32 +0100
committerThomas Haller <thaller@redhat.com>2020-01-28 10:54:14 +0100
commit0382e54d8d0c8515f5a0ccb2f9e92ccb787bb7c4 (patch)
tree7dbadf9ff05d6f0ff7c2e73d34e8cd36c7430d62
parent587c35b1f4cb4e8bf57c15db749bdac51c8505bc (diff)
downloadNetworkManager-0382e54d8d0c8515f5a0ccb2f9e92ccb787bb7c4.tar.gz
libnm: expose nml_cleanup_context_busy_watcher_on_idle() helper for reuse
This can be used by NMSecretAgentOld.
-rw-r--r--libnm/nm-client.c112
-rw-r--r--libnm/nm-libnm-utils.h3
2 files changed, 67 insertions, 48 deletions
diff --git a/libnm/nm-client.c b/libnm/nm-client.c
index 70fff47b92..b530d7d671 100644
--- a/libnm/nm-client.c
+++ b/libnm/nm-client.c
@@ -6971,6 +6971,68 @@ name_owner_get_call (NMClient *self)
/*****************************************************************************/
+static inline gboolean
+_nml_cleanup_context_busy_watcher_on_idle_cb (gpointer user_data)
+{
+ nm_auto_unref_gmaincontext GMainContext *context = NULL;
+ gs_unref_object GObject *context_busy_watcher = NULL;
+
+ nm_utils_user_data_unpack (user_data, &context, &context_busy_watcher);
+
+ nm_assert (context);
+ nm_assert (G_IS_OBJECT (context_busy_watcher));
+ return G_SOURCE_REMOVE;
+}
+
+void
+nml_cleanup_context_busy_watcher_on_idle (GObject *context_busy_watcher_take,
+ GMainContext *context)
+{
+ gs_unref_object GObject *context_busy_watcher = g_steal_pointer (&context_busy_watcher_take);
+ GSource *cleanup_source;
+
+ nm_assert (G_IS_OBJECT (context_busy_watcher));
+ nm_assert (context);
+
+ /* Technically, we cancelled all pending actions (and these actions
+ * (GTask) 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.
+ *
+ * Note that we could also *not* take a reference on @context
+ * and unref @context_busy_watcher via the GDestroyNotify. That would
+ * allow for the context to be wrapped up early, and when the last user
+ * gives up the reference to the context, the destroy notify could complete
+ * without even invoke the idle handler. However, that destroy notify may
+ * not be called in the right thread. So, we want to be sure that we unref
+ * the context-busy-watcher in the right context. Hence, we always take an
+ * additional reference and always cleanup in the idle handler. This means:
+ * the user *MUST* always keep iterating the context after NMClient got destroyed.
+ * But that is not a severe limitation, because the user anyway must be prepared
+ * to do that. That is because in many cases it is necessary anyway (and the user
+ * wouldn't know a priory when not). This way, it is just always necessary. */
+
+ cleanup_source = nm_g_idle_source_new (G_PRIORITY_LOW + 10,
+ _nml_cleanup_context_busy_watcher_on_idle_cb,
+ nm_utils_user_data_pack (g_main_context_ref (context),
+ g_steal_pointer (&context_busy_watcher)),
+ NULL);
+ g_source_attach (cleanup_source, context);
+ g_source_unref (cleanup_source);
+}
+
+/*****************************************************************************/
+
static void
_init_start_complete (NMClient *self,
GError *error_take)
@@ -7568,18 +7630,6 @@ constructed (GObject *object)
NML_NMCLIENT_LOG_D (self, "new NMClient instance");
}
-static inline gboolean
-_dispose_cleanup_context_busy_watcher_cb (gpointer user_data)
-{
- nm_auto_unref_gmaincontext GMainContext *context = NULL;
- gs_unref_object GObject *context_busy_watcher = NULL;
-
- nm_utils_user_data_unpack (user_data, &context, &context_busy_watcher);
-
- nm_assert (G_IS_OBJECT (context_busy_watcher));
- return G_SOURCE_REMOVE;
-}
-
static void
dispose (GObject *object)
{
@@ -7630,42 +7680,8 @@ dispose (GObject *object)
if ( priv->context_busy_watcher
&& priv->dbus_context) {
- GSource *cleanup_source;
-
- /* Technically, we cancelled all pending actions (and these actions
- * (GTask) 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.
- *
- * Note that we could also *not* take a reference on priv->dbus_context
- * and unref priv->context_busy_watcher via the GDestroyNotify. That would
- * allow for the context to be wrapped up early, and when the last user
- * gives up the reference to the context, the destroy notify could complete
- * without even invoke the idle handler. However, that destroy notify may
- * not be called in the right thread. So, we want to be sure that we unref
- * the context-busy-watcher in the right context. Hence, we always take an
- * additional reference and always cleanup in the idle handler. This means:
- * the user *MUST* always keep iterating the context after NMClient got destroyed.
- * But that is not a severe limitation, because the user anyway must be prepared
- * to do that. That is because in many cases it is necessary anyway (and the user
- * wouldn't know a priory when not). This way, it is just always necessary. */
- cleanup_source = nm_g_idle_source_new (G_PRIORITY_LOW + 10,
- _dispose_cleanup_context_busy_watcher_cb,
- nm_utils_user_data_pack (g_main_context_ref (priv->dbus_context),
- g_steal_pointer (&priv->context_busy_watcher)),
- NULL);
- g_source_attach (cleanup_source, priv->dbus_context);
- g_source_unref (cleanup_source);
+ nml_cleanup_context_busy_watcher_on_idle (g_steal_pointer (&priv->context_busy_watcher),
+ priv->dbus_context);
}
nm_clear_pointer (&priv->dbus_context, g_main_context_unref);
diff --git a/libnm/nm-libnm-utils.h b/libnm/nm-libnm-utils.h
index c28e8a622b..f2affc5f62 100644
--- a/libnm/nm-libnm-utils.h
+++ b/libnm/nm-libnm-utils.h
@@ -209,6 +209,9 @@ NMLInitData *nml_init_data_new_async (GCancellable *cancellable,
void nml_init_data_return (NMLInitData *init_data,
GError *error_take);
+void nml_cleanup_context_busy_watcher_on_idle (GObject *context_busy_watcher_take,
+ GMainContext *context);
+
/*****************************************************************************/
typedef struct _NMLDBusObject NMLDBusObject;