From 51dd46b3d990c73559e7b742d5dc64582328d45a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Thu, 22 Jun 2023 00:48:45 -0400 Subject: [PATCH] context: Simplify handling of removal signals We used to notify device removed signal in an idle to ensure that this happened before the context device-removed signal, however this can be achieved also using the after-callbacks without having to imply further idles that complicates the context destruction handling, also causing that a device that has been removed is returned by get_devices() for longer than expected. Simplify the codepath adjusting the tests. They are still checking that the order is preserved. --- libfprint/fp-context.c | 65 +++++++++-------------------------------- tests/test-fp-context.c | 52 +++++---------------------------- 2 files changed, 21 insertions(+), 96 deletions(-) diff --git a/libfprint/fp-context.c b/libfprint/fp-context.c index 77234c04..1561d700 100644 --- a/libfprint/fp-context.c +++ b/libfprint/fp-context.c @@ -89,54 +89,17 @@ is_driver_allowed (const gchar *driver) return g_strv_contains ((const gchar * const *) allowlisted_drivers, driver); } -typedef struct +static void +remove_device (FpContext *context, + FpDevice *device) { - FpContext *context; - FpDevice *device; - GSource *source; -} RemoveDeviceData; - -static gboolean -remove_device_idle_cb (RemoveDeviceData *data) -{ - FpContextPrivate *priv = fp_context_get_instance_private (data->context); + FpContextPrivate *priv = fp_context_get_instance_private (context); guint idx = 0; - g_return_val_if_fail (g_ptr_array_find (priv->devices, data->device, &idx), G_SOURCE_REMOVE); + g_return_if_fail (g_ptr_array_find (priv->devices, device, &idx)); - g_signal_emit (data->context, signals[DEVICE_REMOVED_SIGNAL], 0, data->device); + g_signal_emit (context, signals[DEVICE_REMOVED_SIGNAL], 0, device); g_ptr_array_remove_index_fast (priv->devices, idx); - - return G_SOURCE_REMOVE; -} - -static void -remove_device_data_free (RemoveDeviceData *data) -{ - FpContextPrivate *priv = fp_context_get_instance_private (data->context); - - priv->sources = g_slist_remove (priv->sources, data->source); - g_free (data); -} - -static void -remove_device (FpContext *context, FpDevice *device) -{ - g_autoptr(GSource) source = NULL; - FpContextPrivate *priv = fp_context_get_instance_private (context); - RemoveDeviceData *data; - - data = g_new (RemoveDeviceData, 1); - data->context = context; - data->device = device; - - source = data->source = g_idle_source_new (); - g_source_set_callback (source, - G_SOURCE_FUNC (remove_device_idle_cb), data, - (GDestroyNotify) remove_device_data_free); - g_source_attach (source, g_main_context_get_thread_default ()); - - priv->sources = g_slist_prepend (priv->sources, source); } static void @@ -149,17 +112,13 @@ device_remove_on_notify_open_cb (FpContext *context, GParamSpec *pspec, FpDevice static void device_removed_cb (FpContext *context, FpDevice *device) { - gboolean open = FALSE; - - g_object_get (device, "open", &open, NULL); - /* Wait for device close if the device is currently still open. */ - if (open) + if (fp_device_is_open (device)) { g_signal_connect_object (device, "notify::open", (GCallback) device_remove_on_notify_open_cb, context, - G_CONNECT_SWAPPED); + G_CONNECT_SWAPPED | G_CONNECT_AFTER); } else { @@ -195,7 +154,7 @@ async_device_init_done_cb (GObject *source_object, GAsyncResult *res, gpointer u g_signal_connect_object (device, "removed", (GCallback) device_removed_cb, context, - G_CONNECT_SWAPPED); + G_CONNECT_SWAPPED | G_CONNECT_AFTER); g_signal_emit (context, signals[DEVICE_ADDED_SIGNAL], 0, device); } @@ -275,8 +234,10 @@ usb_device_removed_cb (FpContext *self, GUsbDevice *device, GUsbContext *usb_ctx if (cls->type != FP_DEVICE_TYPE_USB) continue; - if (fpi_device_get_usb_device (dev) == device) - fpi_device_remove (dev); + if (fpi_device_get_usb_device (dev) != device) + continue; + + fpi_device_remove (dev); } } diff --git a/tests/test-fp-context.c b/tests/test-fp-context.c index c74548cd..da33b690 100644 --- a/tests/test-fp-context.c +++ b/tests/test-fp-context.c @@ -121,29 +121,21 @@ static void test_context_remove_device_closed (void) { g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); - gboolean removed; + FpDevice *device = tctx->device; tctx->user_data = NULL; - g_signal_connect (tctx->device, "removed", (GCallback) device_removed_cb, tctx); g_signal_connect (tctx->fp_context, "device-removed", (GCallback) context_device_removed_cb, tctx); + g_signal_connect (tctx->device, "removed", (GCallback) device_removed_cb, tctx); /* Triggering remove on closed device. */ fpi_device_remove (tctx->device); - g_assert_nonnull (tctx->device); - g_object_get (tctx->device, "removed", &removed, NULL); - g_assert_true (removed); - g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB); - - /* device-removed is dispatched from idle. */ - while (g_main_context_iteration (NULL, FALSE)) - { - } - /* The device is now destroyed and device-removed was called. */ g_assert_null (tctx->device); g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB); + g_assert_false (g_ptr_array_find (fp_context_get_devices (tctx->fp_context), device, NULL)); + fpt_teardown_virtual_device_environment (); } @@ -165,6 +157,7 @@ test_context_remove_device_closing (void) g_autoptr(FptContext) tctx = fpt_context_new_with_virtual_device (FPT_VIRTUAL_DEVICE_IMAGE); g_autoptr(GError) close_error = NULL; g_autoptr(GError) error = NULL; + FpDevice *device = tctx->device; gboolean removed; tctx->user_data = NULL; @@ -190,17 +183,11 @@ test_context_remove_device_closing (void) g_assert_error (close_error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED); /* Now the removed callback has been called already. */ - g_assert_nonnull (tctx->device); - g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB); - - /* While device-removed needs another idle iteration. */ - while (g_main_context_iteration (NULL, FALSE)) - { - } - g_assert_null (tctx->device); g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB); + g_assert_false (g_ptr_array_find (fp_context_get_devices (tctx->fp_context), device, NULL)); + fpt_teardown_virtual_device_environment (); } @@ -234,16 +221,9 @@ test_context_remove_device_open (void) } g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB); - /* On close, the device will be removed from the context, - * but only a main loop iteration later. */ + /* On close, the device will be removed from the context */ fp_device_close_sync (tctx->device, NULL, &error); g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED); - g_assert_nonnull (tctx->device); - g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB); - - while (g_main_context_iteration (NULL, FALSE)) - { - } g_assert_null (tctx->device); g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB); @@ -298,14 +278,6 @@ test_context_remove_device_opening (void) fp_device_close_sync (tctx->device, NULL, &close_error); g_assert_error (close_error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED); - g_assert_nonnull (tctx->device); - g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB); - - /* The device-removed signal needs an idle iteration. */ - while (g_main_context_iteration (NULL, FALSE)) - { - } - g_assert_null (tctx->device); g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB); @@ -369,14 +341,6 @@ test_context_remove_device_active (void) /* Now we close the device, state remains unchanged mostly. */ fp_device_close_sync (tctx->device, NULL, &error); g_assert_error (error, FP_DEVICE_ERROR, FP_DEVICE_ERROR_REMOVED); - g_assert_nonnull (tctx->device); - g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, DEV_REMOVED_CB); - - /* And "device-removed" is called */ - while (g_main_context_iteration (NULL, FALSE)) - { - } - g_assert_null (tctx->device); g_assert_cmpint (GPOINTER_TO_INT (tctx->user_data), ==, CTX_DEVICE_REMOVED_CB);