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.
This commit is contained in:
Thomas Haller 2017-04-22 12:19:27 +02:00
parent e84a52ea42
commit 44f5e372ce

View file

@ -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);