summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2014-10-03 12:46:12 +0200
committerThomas Haller <thaller@redhat.com>2014-10-03 12:46:24 +0200
commitd4cd8b578596e7698c48eb6be02bcbfd678256b0 (patch)
tree8b91f4587262d02385eb2f6567f4dfbabb836b32
parent20a746f68a0f5e6ea170f86099d71ea5a2c20e49 (diff)
parent97b2c1b0d154a27516a9eba2fc67076ce324681c (diff)
downloadNetworkManager-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.c98
-rw-r--r--libnm/nm-object.c33
-rw-r--r--libnm/nm-object.h1
-rw-r--r--src/nm-dbus-manager.c9
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,