diff options
author | Thomas Haller <thaller@redhat.com> | 2017-04-22 12:19:27 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-05-11 18:57:23 +0200 |
commit | b83a9525b96070cc6f38d9dd9ee20594e3ab7d21 (patch) | |
tree | ecb9547d5f11ca3d6603c1d681659ddd4344ed7f | |
parent | 5a2151937db1c37ce79d1bd90f524eee73283157 (diff) | |
download | NetworkManager-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.c | 93 |
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); |