diff options
author | Thomas Haller <thaller@redhat.com> | 2014-10-03 12:46:12 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2014-10-03 12:46:24 +0200 |
commit | d4cd8b578596e7698c48eb6be02bcbfd678256b0 (patch) | |
tree | 8b91f4587262d02385eb2f6567f4dfbabb836b32 | |
parent | 20a746f68a0f5e6ea170f86099d71ea5a2c20e49 (diff) | |
parent | 97b2c1b0d154a27516a9eba2fc67076ce324681c (diff) | |
download | NetworkManager-d4cd8b578596e7698c48eb6be02bcbfd678256b0.tar.gz |
libnm: merge branch 'th/bgo737725-libnm-private-dbus-connection'
https://bugzilla.gnome.org/show_bug.cgi?id=737725
Signed-off-by: Thomas Haller <thaller@redhat.com>
-rw-r--r-- | libnm/nm-dbus-helpers.c | 98 | ||||
-rw-r--r-- | libnm/nm-object.c | 33 | ||||
-rw-r--r-- | libnm/nm-object.h | 1 | ||||
-rw-r--r-- | src/nm-dbus-manager.c | 9 |
4 files changed, 128 insertions, 13 deletions
diff --git a/libnm/nm-dbus-helpers.c b/libnm/nm-dbus-helpers.c index 10f5913305..4c0318dd2e 100644 --- a/libnm/nm-dbus-helpers.c +++ b/libnm/nm-dbus-helpers.c @@ -41,6 +41,51 @@ _nm_dbus_bus_type (void) return nm_bus; } +static struct { + GMutex mutex; + GWeakRef weak_ref; +} private_connection; + +static void +_private_dbus_connection_closed_cb (GDBusConnection *connection, + gboolean remote_peer_vanished, + GError *error, + gpointer user_data) +{ + GDBusConnection *p; + + g_mutex_lock (&private_connection.mutex); + p = g_weak_ref_get (&private_connection.weak_ref); + if (connection == p) { + g_signal_handlers_disconnect_by_func (G_OBJECT (connection), G_CALLBACK (_private_dbus_connection_closed_cb), NULL); + g_weak_ref_set (&private_connection.weak_ref, NULL); + } + if (p) + g_object_unref (p); + g_mutex_unlock (&private_connection.mutex); +} + +static GDBusConnection * +_private_dbus_connection_internalize (GDBusConnection *connection) +{ + GDBusConnection *p; + + g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL); + g_return_val_if_fail (!g_dbus_connection_is_closed (connection), NULL); + + g_mutex_lock (&private_connection.mutex); + p = g_weak_ref_get (&private_connection.weak_ref); + if (p) { + g_object_unref (connection); + connection = p; + } else { + g_weak_ref_set (&private_connection.weak_ref, connection); + g_signal_connect (connection, "closed", G_CALLBACK (_private_dbus_connection_closed_cb), NULL); + } + g_mutex_unlock (&private_connection.mutex); + return connection; +} + GDBusConnection * _nm_dbus_new_connection (GCancellable *cancellable, GError **error) { @@ -49,12 +94,17 @@ _nm_dbus_new_connection (GCancellable *cancellable, GError **error) /* If running as root try the private bus first */ if (0 == geteuid ()) { GError *local = NULL; + GDBusConnection *p; + + p = g_weak_ref_get (&private_connection.weak_ref); + if (p) + return p; connection = g_dbus_connection_new_for_address_sync ("unix:path=" NMRUNDIR "/private", G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, NULL, cancellable, &local); if (connection) - return connection; + return _private_dbus_connection_internalize (connection); if (g_error_matches (local, G_IO_ERROR, G_IO_ERROR_CANCELLED)) { g_propagate_error (error, local); @@ -92,6 +142,7 @@ new_connection_async_got_private (GObject *source, GAsyncResult *result, gpointe connection = g_dbus_connection_new_for_address_finish (result, &error); if (connection) { + connection = _private_dbus_connection_internalize (connection); g_simple_async_result_set_op_res_gpointer (simple, connection, g_object_unref); g_simple_async_result_complete (simple); g_object_unref (simple); @@ -111,6 +162,36 @@ new_connection_async_got_private (GObject *source, GAsyncResult *result, gpointe new_connection_async_got_system, simple); } +static void +_nm_dbus_new_connection_async_do (GSimpleAsyncResult *simple, GCancellable *cancellable) +{ + g_dbus_connection_new_for_address ("unix:path=" NMRUNDIR "/private", + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + cancellable, + new_connection_async_got_private, simple); +} + +static gboolean +_nm_dbus_new_connection_async_get_private (gpointer user_data) +{ + GSimpleAsyncResult *simple = user_data; + GDBusConnection *p; + + p = g_weak_ref_get (&private_connection.weak_ref); + if (!p) { + /* The connection is gone. Create a new one async... */ + _nm_dbus_new_connection_async_do (simple, + g_object_get_data (G_OBJECT (simple), "cancellable")); + } else { + g_simple_async_result_set_op_res_gpointer (simple, p, g_object_unref); + g_simple_async_result_complete (simple); + g_object_unref (simple); + } + + return G_SOURCE_REMOVE; +} + void _nm_dbus_new_connection_async (GCancellable *cancellable, GAsyncReadyCallback callback, @@ -122,15 +203,18 @@ _nm_dbus_new_connection_async (GCancellable *cancellable, /* If running as root try the private bus first */ if (0 == geteuid ()) { + GDBusConnection *p; + if (cancellable) { g_object_set_data_full (G_OBJECT (simple), "cancellable", - g_object_ref (cancellable), g_object_unref); + g_object_ref (cancellable), g_object_unref); } - g_dbus_connection_new_for_address ("unix:path=" NMRUNDIR "/private", - G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, - NULL, - cancellable, - new_connection_async_got_private, simple); + p = g_weak_ref_get (&private_connection.weak_ref); + if (p) { + g_object_unref (p); + g_idle_add (_nm_dbus_new_connection_async_get_private, simple); + } else + _nm_dbus_new_connection_async_do (simple, cancellable); } else { g_bus_get (_nm_dbus_bus_type (), cancellable, diff --git a/libnm/nm-object.c b/libnm/nm-object.c index 027f66bd8f..f3d758e422 100644 --- a/libnm/nm-object.c +++ b/libnm/nm-object.c @@ -72,7 +72,6 @@ static void reload_complete (NMObject *object); typedef struct { GDBusConnection *connection; - gboolean private_connection; gboolean nm_running; char *path; @@ -93,6 +92,7 @@ typedef struct { enum { PROP_0, PROP_PATH, + PROP_DBUS_CONNECTION, PROP_NM_RUNNING, LAST_PROP @@ -175,7 +175,8 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) return FALSE; } - priv->connection = _nm_dbus_new_connection (cancellable, error); + if (!priv->connection) + priv->connection = _nm_dbus_new_connection (cancellable, error); if (!priv->connection) return FALSE; @@ -380,6 +381,10 @@ set_property (GObject *object, guint prop_id, /* Construct only */ priv->path = g_value_dup_string (value); break; + case PROP_DBUS_CONNECTION: + /* Construct only */ + priv->connection = g_value_dup_object (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -396,6 +401,9 @@ get_property (GObject *object, guint prop_id, case PROP_PATH: g_value_set_string (value, priv->path); break; + case PROP_DBUS_CONNECTION: + g_value_set_object (value, priv->connection); + break; case PROP_NM_RUNNING: g_value_set_boolean (value, priv->nm_running); break; @@ -436,6 +444,19 @@ nm_object_class_init (NMObjectClass *nm_object_class) G_PARAM_STATIC_STRINGS)); /** + * NMObject:dbus-connection: (skip) + * + * The #GDBusConnection of the object. + **/ + g_object_class_install_property + (object_class, PROP_DBUS_CONNECTION, + g_param_spec_object (NM_OBJECT_DBUS_CONNECTION, "", "", + G_TYPE_DBUS_CONNECTION, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** * NMObject:manager-running: (skip) * * Internal use only. @@ -499,9 +520,12 @@ _nm_object_class_add_interface (NMObjectClass *object_class, NMObjectClassPrivate *cpriv; g_return_if_fail (NM_IS_OBJECT_CLASS (object_class)); + g_return_if_fail (interface); cpriv = NM_OBJECT_CLASS_GET_PRIVATE (object_class); + g_return_if_fail (g_slist_find_custom (cpriv->interfaces, interface, (GCompareFunc) g_strcmp0) == NULL); + cpriv->interfaces = g_slist_prepend (cpriv->interfaces, g_strdup (interface)); } @@ -668,6 +692,7 @@ _nm_object_create (GType type, GDBusConnection *connection, const char *path) object = g_object_new (type, NM_OBJECT_PATH, path, + NM_OBJECT_DBUS_CONNECTION, connection, NULL); /* Cache the object before initializing it (and in particular, loading its * property values); this is necessary to make circular references work (eg, @@ -692,6 +717,7 @@ typedef struct { NMObjectCreateCallbackFunc callback; gpointer user_data; NMObjectTypeFuncData *type_data; + GDBusConnection *connection; } NMObjectTypeAsyncData; static void @@ -700,6 +726,7 @@ create_async_complete (GObject *object, NMObjectTypeAsyncData *async_data) async_data->callback (object, async_data->path, async_data->user_data); g_free (async_data->path); + g_object_unref (async_data->connection); g_slice_free (NMObjectTypeAsyncData, async_data); } @@ -747,6 +774,7 @@ create_async_got_type (NMObjectTypeAsyncData *async_data, GType type) object = g_object_new (type, NM_OBJECT_PATH, async_data->path, + NM_OBJECT_DBUS_CONNECTION, async_data->connection, NULL); g_async_initable_init_async (G_ASYNC_INITABLE (object), G_PRIORITY_DEFAULT, NULL, create_async_inited, async_data); @@ -813,6 +841,7 @@ _nm_object_create_async (GType type, GDBusConnection *connection, const char *pa async_data->path = g_strdup (path); async_data->callback = callback; async_data->user_data = user_data; + async_data->connection = g_object_ref (connection); async_data->type_data = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type)); if (async_data->type_data) { diff --git a/libnm/nm-object.h b/libnm/nm-object.h index 1ad83a915c..69232364f4 100644 --- a/libnm/nm-object.h +++ b/libnm/nm-object.h @@ -56,6 +56,7 @@ typedef enum { GQuark nm_object_error_quark (void); #define NM_OBJECT_PATH "path" +#define NM_OBJECT_DBUS_CONNECTION "dbus-connection" typedef struct { GObject parent; diff --git a/src/nm-dbus-manager.c b/src/nm-dbus-manager.c index 97f9ad56dc..46abe3612d 100644 --- a/src/nm-dbus-manager.c +++ b/src/nm-dbus-manager.c @@ -110,11 +110,12 @@ private_server_message_filter (DBusConnection *conn, void *data) { PrivateServer *s = data; + int fd; /* Clean up after the connection */ if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")) { - nm_log_dbg (LOGD_CORE, "(%s) closed connection %p on private socket.", - s->tag, conn); + nm_log_dbg (LOGD_CORE, "(%s) closed connection %p on private socket (fd %d).", + s->tag, conn, dbus_connection_get_unix_fd (conn, &fd) ? fd : -1); /* Emit this for the manager */ g_signal_emit (s->manager, @@ -158,8 +159,8 @@ private_server_new_connection (DBusServer *server, sender = g_strdup_printf ("x:y:%d", counter++); g_hash_table_insert (s->connections, dbus_connection_ref (conn), sender); - nm_log_dbg (LOGD_CORE, "(%s) accepted connection %p on private socket (fd %"G_GINT64_FORMAT").", - s->tag, conn, dbus_connection_get_unix_fd (conn, &fd) ? fd : G_MININT64); + nm_log_dbg (LOGD_CORE, "(%s) accepted connection %p on private socket (fd %d).", + s->tag, conn, dbus_connection_get_unix_fd (conn, &fd) ? fd : -1); /* Emit this for the manager */ g_signal_emit (s->manager, |