summary refs log tree commit diff
path: root/libnm
diff options
context:
space:
mode:
Diffstat (limited to 'libnm')
-rw-r--r--libnm/nm-client.c117
-rw-r--r--libnm/nm-device-wifi-p2p.c8
-rw-r--r--libnm/nm-wifi-p2p-peer.c20
3 files changed, 117 insertions, 28 deletions
diff --git a/libnm/nm-client.c b/libnm/nm-client.c
index eabbe022..4fa1c1f3 100644
--- a/libnm/nm-client.c
+++ b/libnm/nm-client.c
@@ -2988,9 +2988,12 @@ _dbus_handle_interface_removed (NMClient *self,
 }
 
 static void
-_dbus_managed_objects_changed_cb (const char *object_path,
-                                  GVariant *added_interfaces_and_properties,
-                                  const char *const*removed_interfaces,
+_dbus_managed_objects_changed_cb (GDBusConnection *connection,
+                                  const char *sender_name,
+                                  const char *arg_object_path,
+                                  const char *interface_name,
+                                  const char *signal_name,
+                                  GVariant *parameters,
                                   gpointer user_data)
 {
 	NMClient *self = user_data;
@@ -2998,19 +3001,50 @@ _dbus_managed_objects_changed_cb (const char *object_path,
 	const char *log_context;
 	gboolean changed;
 
+	nm_assert (nm_streq0 (interface_name, DBUS_INTERFACE_OBJECT_MANAGER));
+
 	if (priv->get_managed_objects_cancellable) {
 		/* we still wait for the initial GetManagedObjects(). Ignore the event. */
 		return;
 	}
 
-	if (!added_interfaces_and_properties) {
-		log_context = "interfaces-removed";
-		changed = _dbus_handle_interface_removed (self, log_context, object_path, NULL, removed_interfaces);
-	} else {
+	if (nm_streq (signal_name, "InterfacesAdded")) {
+		gs_unref_variant GVariant *interfaces_and_properties = NULL;
+		const char *object_path;
+
+		if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(oa{sa{sv}})")))
+			return;
+
+		g_variant_get (parameters,
+		               "(&o@a{sa{sv}})",
+		               &object_path,
+		               &interfaces_and_properties);
+
 		log_context = "interfaces-added";
-		changed = _dbus_handle_interface_added (self, log_context, object_path, added_interfaces_and_properties);
+		changed = _dbus_handle_interface_added (self, log_context, object_path, interfaces_and_properties);
+		goto out;
+	}
+
+	if (nm_streq (signal_name, "InterfacesRemoved")) {
+		gs_free const char **interfaces = NULL;
+		const char *object_path;
+
+		if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(oas)")))
+			return;
+
+		g_variant_get (parameters,
+		               "(&o^a&s)",
+		               &object_path,
+		               &interfaces);
+
+		log_context = "interfaces-removed";
+		changed = _dbus_handle_interface_removed (self, log_context, object_path, NULL, interfaces);
+		goto out;
 	}
 
+	return;
+
+out:
 	if (changed)
 		_dbus_handle_changes (self, log_context, TRUE);
 }
@@ -5143,7 +5177,7 @@ nm_client_add_and_activate_connection2_finish (NMClient *client,
 {
 	return NM_ACTIVE_CONNECTION (_request_wait_finish (client,
 	                                                   result,
-	                                                   nm_client_add_connection2,
+	                                                   nm_client_add_and_activate_connection2,
 	                                                   out_result,
 	                                                   error));
 }
@@ -6512,12 +6546,13 @@ _init_fetch_all (NMClient *self)
 
 	priv->get_managed_objects_cancellable = g_cancellable_new ();
 
-	priv->dbsid_nm_object_manager = nm_dbus_connection_signal_subscribe_object_manager (priv->dbus_connection,
-	                                                                                    priv->name_owner,
-	                                                                                    "/org/freedesktop",
-	                                                                                    _dbus_managed_objects_changed_cb,
-	                                                                                    self,
-	                                                                                    NULL);
+	priv->dbsid_nm_object_manager = nm_dbus_connection_signal_subscribe_object_manager_plain (priv->dbus_connection,
+	                                                                                          priv->name_owner,
+	                                                                                          "/org/freedesktop",
+	                                                                                          NULL,
+	                                                                                          _dbus_managed_objects_changed_cb,
+	                                                                                          self,
+	                                                                                          NULL);
 
 	priv->dbsid_dbus_properties_properties_changed = nm_dbus_connection_signal_subscribe_properties_changed (priv->dbus_connection,
 	                                                                                                         priv->name_owner,
@@ -7398,6 +7433,18 @@ 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)
 {
@@ -7446,6 +7493,46 @@ 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
+		 * (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);
+	}
+
 	nm_clear_pointer (&priv->dbus_context, g_main_context_unref);
 	nm_clear_pointer (&priv->main_context, g_main_context_unref);
 
diff --git a/libnm/nm-device-wifi-p2p.c b/libnm/nm-device-wifi-p2p.c
index 191d30eb..aa5089c7 100644
--- a/libnm/nm-device-wifi-p2p.c
+++ b/libnm/nm-device-wifi-p2p.c
@@ -165,8 +165,8 @@ nm_device_wifi_p2p_start_find (NMDeviceWifiP2P *device,
 	                      cancellable,
 	                      callback,
 	                      user_data,
-	                      NM_DBUS_PATH,
-	                      NM_DBUS_INTERFACE,
+	                      _nm_object_get_path (device),
+	                      NM_DBUS_INTERFACE_DEVICE_WIFI_P2P,
 	                      "StartFind",
 	                      g_variant_new ("(@a{sv})", options),
 	                      G_VARIANT_TYPE ("()"),
@@ -224,8 +224,8 @@ nm_device_wifi_p2p_stop_find (NMDeviceWifiP2P     *device,
 	                      cancellable,
 	                      callback,
 	                      user_data,
-	                      NM_DBUS_PATH,
-	                      NM_DBUS_INTERFACE,
+	                      _nm_object_get_path (device),
+	                      NM_DBUS_INTERFACE_DEVICE_WIFI_P2P,
 	                      "StopFind",
 	                      g_variant_new ("()"),
 	                      G_VARIANT_TYPE ("()"),
diff --git a/libnm/nm-wifi-p2p-peer.c b/libnm/nm-wifi-p2p-peer.c
index 50910445..9edf0848 100644
--- a/libnm/nm-wifi-p2p-peer.c
+++ b/libnm/nm-wifi-p2p-peer.c
@@ -409,15 +409,17 @@ const NMLDBusMetaIface _nml_dbus_meta_iface_nm_wifip2ppeer = NML_DBUS_META_IFACE
 	nm_wifi_p2p_peer_get_type,
 	NML_DBUS_META_INTERFACE_PRIO_INSTANTIATE_HIGH,
 	NML_DBUS_META_IFACE_DBUS_PROPERTIES (
-		NML_DBUS_META_PROPERTY_INIT_U  ("Flags",        PROP_FLAGS,        NMWifiP2PPeer, _priv.flags        ),
-		NML_DBUS_META_PROPERTY_INIT_S  ("HwAddress",    PROP_HW_ADDRESS,   NMWifiP2PPeer, _priv.hw_address   ),
-		NML_DBUS_META_PROPERTY_INIT_I  ("LastSeen",     PROP_LAST_SEEN,    NMWifiP2PPeer, _priv.last_seen    ),
-		NML_DBUS_META_PROPERTY_INIT_S  ("Manufacturer", PROP_MANUFACTURER, NMWifiP2PPeer, _priv.manufacturer ),
-		NML_DBUS_META_PROPERTY_INIT_S  ("Model",        PROP_MODEL,        NMWifiP2PPeer, _priv.model        ),
-		NML_DBUS_META_PROPERTY_INIT_S  ("ModelNumber",  PROP_MODEL_NUMBER, NMWifiP2PPeer, _priv.model_number ),
-		NML_DBUS_META_PROPERTY_INIT_S  ("Serial",       PROP_SERIAL,       NMWifiP2PPeer, _priv.serial       ),
-		NML_DBUS_META_PROPERTY_INIT_Y  ("Strength",     PROP_STRENGTH,     NMWifiP2PPeer, _priv.strength     ),
-		NML_DBUS_META_PROPERTY_INIT_AY ("WfdIEs",       PROP_WFD_IES,      NMWifiP2PPeer, _priv.wfd_ies      ),
+		NML_DBUS_META_PROPERTY_INIT_U      ("Flags",        PROP_FLAGS,        NMWifiP2PPeer, _priv.flags        ),
+		NML_DBUS_META_PROPERTY_INIT_IGNORE ("Groups",       "as"                                                 ),
+		NML_DBUS_META_PROPERTY_INIT_S      ("HwAddress",    PROP_HW_ADDRESS,   NMWifiP2PPeer, _priv.hw_address   ),
+		NML_DBUS_META_PROPERTY_INIT_I      ("LastSeen",     PROP_LAST_SEEN,    NMWifiP2PPeer, _priv.last_seen    ),
+		NML_DBUS_META_PROPERTY_INIT_S      ("Manufacturer", PROP_MANUFACTURER, NMWifiP2PPeer, _priv.manufacturer ),
+		NML_DBUS_META_PROPERTY_INIT_S      ("Model",        PROP_MODEL,        NMWifiP2PPeer, _priv.model        ),
+		NML_DBUS_META_PROPERTY_INIT_S      ("ModelNumber",  PROP_MODEL_NUMBER, NMWifiP2PPeer, _priv.model_number ),
+		NML_DBUS_META_PROPERTY_INIT_S      ("Name",         PROP_NAME,         NMWifiP2PPeer, _priv.name         ),
+		NML_DBUS_META_PROPERTY_INIT_S      ("Serial",       PROP_SERIAL,       NMWifiP2PPeer, _priv.serial       ),
+		NML_DBUS_META_PROPERTY_INIT_Y      ("Strength",     PROP_STRENGTH,     NMWifiP2PPeer, _priv.strength     ),
+		NML_DBUS_META_PROPERTY_INIT_AY     ("WfdIEs",       PROP_WFD_IES,      NMWifiP2PPeer, _priv.wfd_ies      ),
 	),
 );