summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-04-22 12:19:27 +0200
committerThomas Haller <thaller@redhat.com>2017-05-11 18:57:23 +0200
commitb83a9525b96070cc6f38d9dd9ee20594e3ab7d21 (patch)
treeecb9547d5f11ca3d6603c1d681659ddd4344ed7f
parent5a2151937db1c37ce79d1bd90f524eee73283157 (diff)
downloadNetworkManager-b83a9525b96070cc6f38d9dd9ee20594e3ab7d21.tar.gz
bt: create D-Bus proxy for NMBluez4Adapter asynchronously
And some fixes: - proxy creation may fail. Don't handle it by retrying, but at least don't access the invalid proxy instance. - get_properties_cb() did not take a reference to @self nor was the operation cancellable. This leads to crash if the instance gets destroyed early.
-rw-r--r--src/devices/bluetooth/nm-bluez4-adapter.c93
1 files changed, 68 insertions, 25 deletions
diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c
index c0c1be30b7..5c09582b04 100644
--- a/src/devices/bluetooth/nm-bluez4-adapter.c
+++ b/src/devices/bluetooth/nm-bluez4-adapter.c
@@ -49,6 +49,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
typedef struct {
char *path;
GDBusProxy *proxy;
+ GCancellable *proxy_cancellable;
gboolean initialized;
char *address;
@@ -198,19 +199,28 @@ device_removed (GDBusProxy *proxy, const char *path, gpointer user_data)
static void
get_properties_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
{
- NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data);
- NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
- GError *err = NULL;
+ NMBluez4Adapter *self;
+ NMBluez4AdapterPrivate *priv;
+ gs_free_error GError *error = NULL;
GVariant *ret, *properties;
char **devices;
int i;
ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result,
- G_VARIANT_TYPE ("(a{sv})"), &err);
+ G_VARIANT_TYPE ("(a{sv})"), &error);
+
+ if ( !ret
+ && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ self = NM_BLUEZ4_ADAPTER (user_data);
+ priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
+
+ g_clear_object (&priv->proxy_cancellable);
+
if (!ret) {
- g_dbus_error_strip_remote_error (err);
- nm_log_warn (LOGD_BT, "bluez error getting adapter properties: %s", err->message);
- g_error_free (err);
+ g_dbus_error_strip_remote_error (error);
+ nm_log_warn (LOGD_BT, "bluez error getting adapter properties: %s", error->message);
goto done;
}
@@ -233,15 +243,43 @@ done:
}
static void
-query_properties (NMBluez4Adapter *self)
+_proxy_new_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
+ NMBluez4Adapter *self;
+ NMBluez4AdapterPrivate *priv;
+ gs_free_error GError *error = NULL;
+ GDBusProxy *proxy;
+
+ proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
+ if ( !proxy
+ && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ self = user_data;
+ priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
+
+ if (!proxy) {
+ nm_log_warn (LOGD_BT, "bluez error creating D-Bus proxy: %s", error->message);
+ g_clear_object (&priv->proxy_cancellable);
+ g_signal_emit (self, signals[INITIALIZED], 0, priv->initialized);
+ return;
+ }
+
+ priv->proxy = proxy;
+
+ _nm_dbus_signal_connect (priv->proxy, "DeviceCreated", G_VARIANT_TYPE ("(o)"),
+ G_CALLBACK (device_created), self);
+ _nm_dbus_signal_connect (priv->proxy, "DeviceRemoved", G_VARIANT_TYPE ("(o)"),
+ G_CALLBACK (device_removed), self);
g_dbus_proxy_call (priv->proxy, "GetProperties",
NULL,
G_DBUS_CALL_FLAGS_NONE, -1,
- NULL,
- get_properties_cb, self);
+ priv->proxy_cancellable,
+ get_properties_cb,
+ self);
}
/*****************************************************************************/
@@ -316,19 +354,17 @@ nm_bluez4_adapter_new (const char *path, NMSettings *settings)
priv->settings = g_object_ref (settings);
- priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
- NULL,
- BLUEZ_SERVICE,
- priv->path,
- BLUEZ4_ADAPTER_INTERFACE,
- NULL, NULL);
- _nm_dbus_signal_connect (priv->proxy, "DeviceCreated", G_VARIANT_TYPE ("(o)"),
- G_CALLBACK (device_created), self);
- _nm_dbus_signal_connect (priv->proxy, "DeviceRemoved", G_VARIANT_TYPE ("(o)"),
- G_CALLBACK (device_removed), self);
+ priv->proxy_cancellable = g_cancellable_new ();
- query_properties (self);
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+ NULL,
+ BLUEZ_SERVICE,
+ priv->path,
+ BLUEZ4_ADAPTER_INTERFACE,
+ priv->proxy_cancellable,
+ _proxy_new_cb,
+ self);
return self;
}
@@ -339,21 +375,28 @@ dispose (GObject *object)
NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
NMBluezDevice *device;
+ nm_clear_g_cancellable (&priv->proxy_cancellable);
+
while ((device = g_hash_table_find (priv->devices, _find_all, NULL)))
device_do_remove (self, device);
+ if (priv->proxy) {
+ g_signal_handlers_disconnect_by_data (priv->proxy, self);
+ g_clear_object (&priv->proxy);
+ }
+
G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->dispose (object);
}
static void
finalize (GObject *object)
{
- NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE ((NMBluez4Adapter *) object);
+ NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (object);
+ NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self);
g_hash_table_destroy (priv->devices);
g_free (priv->address);
g_free (priv->path);
- g_object_unref (priv->proxy);
G_OBJECT_CLASS (nm_bluez4_adapter_parent_class)->finalize (object);