aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2017-02-01 21:29:00 +0100
committerAleksander Morgado <aleksander@aleksander.es>2017-02-01 22:59:30 +0100
commit4fa04c8e4c24ca448901169ecf7f9836eebb45ba (patch)
treeff615df1d2c6ab68d560ae198dbdafb837c9c96a
parent195cd3bc9a6481976106ef34a5f85956e19f01b1 (diff)
downloadexternal_libqmi-4fa04c8e4c24ca448901169ecf7f9836eebb45ba.zip
external_libqmi-4fa04c8e4c24ca448901169ecf7f9836eebb45ba.tar.gz
external_libqmi-4fa04c8e4c24ca448901169ecf7f9836eebb45ba.tar.bz2
qmi-firmware-update: GUdevDevice shouldn't outlive the GUdevClient
Make sure all GUdevDevice objects created during the helper methods aren't unref-ed after the GUdevClient that created them. This is because the udev context is owned by the GUdevClient but also used (without any full reference) by all udev_devices (i.e. GUdevDevices) created from that same context. Quite easy to reproduce when using libudev < 218.
-rw-r--r--src/qmi-firmware-update/qfu-udev-helpers.c96
1 files changed, 43 insertions, 53 deletions
diff --git a/src/qmi-firmware-update/qfu-udev-helpers.c b/src/qmi-firmware-update/qfu-udev-helpers.c
index c789703..da07309 100644
--- a/src/qmi-firmware-update/qfu-udev-helpers.c
+++ b/src/qmi-firmware-update/qfu-udev-helpers.c
@@ -46,49 +46,6 @@ qfu_udev_helper_device_type_to_string (QfuUdevHelperDeviceType type)
/******************************************************************************/
-static GUdevDevice *
-find_udev_device_for_file (GFile *file,
- GError **error)
-{
- GUdevClient *client = NULL;
- GUdevDevice *device = NULL;
- gchar *basename = NULL;
- const gchar **subsys_list = NULL;
- guint i;
-
- basename = g_file_get_basename (file);
- if (!basename) {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "couldn't get filename");
- goto out;
- }
-
- client = g_udev_client_new (NULL);
-
- if (g_str_has_prefix (basename, "tty"))
- subsys_list = tty_subsys_list;
- else if (g_str_has_prefix (basename, "cdc-wdm"))
- subsys_list = cdc_wdm_subsys_list;
- else {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "unknown device file type");
- goto out;
- }
-
- for (i = 0; !device && subsys_list[i]; i++)
- device = g_udev_client_query_by_subsystem_and_name (client, subsys_list[i], basename);
-
- if (!device) {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "device not found");
- goto out;
- }
-
-out:
- g_free (basename);
- if (client)
- g_object_unref (client);
-
- return device;
-}
-
static gboolean
udev_helper_get_udev_device_details (GUdevDevice *device,
gchar **out_sysfs_path,
@@ -202,19 +159,52 @@ udev_helper_get_udev_interface_details (GUdevDevice *device,
/******************************************************************************/
gchar *
-qfu_udev_helper_find_by_file (GFile *file,
- GError **error)
+qfu_udev_helper_find_by_file (GFile *file,
+ GError **error)
{
- GUdevDevice *device;
- gchar *sysfs_path = NULL;
+ GUdevClient *client = NULL;
+ GUdevDevice *device = NULL;
+ gchar *basename = NULL;
+ const gchar **subsys_list = NULL;
+ gchar *sysfs_path = NULL;
+ guint i;
- device = find_udev_device_for_file (file, error);
- if (device) {
- udev_helper_get_udev_device_details (device,
- &sysfs_path, NULL, NULL, NULL, NULL,
- error);
- g_object_unref (device);
+ basename = g_file_get_basename (file);
+ if (!basename) {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "couldn't get filename");
+ goto out;
}
+
+ client = g_udev_client_new (NULL);
+
+ if (g_str_has_prefix (basename, "tty"))
+ subsys_list = tty_subsys_list;
+ else if (g_str_has_prefix (basename, "cdc-wdm"))
+ subsys_list = cdc_wdm_subsys_list;
+ else {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "unknown device file type");
+ goto out;
+ }
+
+ for (i = 0; !device && subsys_list[i]; i++)
+ device = g_udev_client_query_by_subsystem_and_name (client, subsys_list[i], basename);
+
+ if (!device) {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "device not found");
+ goto out;
+ }
+
+ if (!udev_helper_get_udev_device_details (device,
+ &sysfs_path, NULL, NULL, NULL, NULL,
+ error))
+ goto out;
+
+ g_debug ("[qfu-udev] sysfs path for '%s' found: %s", basename, sysfs_path);
+
+out:
+ g_free (basename);
+ g_clear_object (&device);
+ g_clear_object (&client);
return sysfs_path;
}