device: Always use an internal cancellable for tasks

This will allow libfprint to cancel operations internally in the future.

If the internal cancellation method is used, then the private
current_cancellation_reason variable must be set to the GError. This
error will be returned when set.
This commit is contained in:
Benjamin Berg
2021-04-21 20:08:48 +02:00
parent a2d950044d
commit 71e0c29f28
5 changed files with 103 additions and 34 deletions

View File

@@ -490,14 +490,11 @@ gboolean
fpi_device_action_is_cancelled (FpDevice *device)
{
FpDevicePrivate *priv = fp_device_get_instance_private (device);
GCancellable *cancellable;
g_return_val_if_fail (FP_IS_DEVICE (device), TRUE);
g_return_val_if_fail (priv->current_action != FPI_DEVICE_ACTION_NONE, TRUE);
cancellable = g_task_get_cancellable (priv->current_task);
return g_cancellable_is_cancelled (cancellable);
return g_cancellable_is_cancelled (priv->current_cancellable);
}
/**
@@ -675,7 +672,7 @@ fpi_device_get_cancellable (FpDevice *device)
g_return_val_if_fail (FP_IS_DEVICE (device), NULL);
g_return_val_if_fail (priv->current_action != FPI_DEVICE_ACTION_NONE, NULL);
return g_task_get_cancellable (priv->current_task);
return priv->current_cancellable;
}
static void
@@ -813,10 +810,17 @@ clear_device_cancel_action (FpDevice *device)
if (priv->current_cancellable_id)
{
g_cancellable_disconnect (g_task_get_cancellable (priv->current_task),
g_cancellable_disconnect (priv->current_cancellable,
priv->current_cancellable_id);
priv->current_cancellable_id = 0;
}
if (priv->current_task_cancellable_id)
{
g_cancellable_disconnect (g_task_get_cancellable (priv->current_task),
priv->current_task_cancellable_id);
priv->current_task_cancellable_id = 0;
}
}
typedef enum _FpDeviceTaskReturnType {
@@ -843,6 +847,7 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
FpiDeviceAction action;
g_autoptr(GTask) task = NULL;
g_autoptr(GError) cancellation_reason = NULL;
action_str = g_enum_to_string (FPI_TYPE_DEVICE_ACTION, priv->current_action);
@@ -852,6 +857,8 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
action = priv->current_action;
priv->current_action = FPI_DEVICE_ACTION_NONE;
priv->current_task_idle_return_source = NULL;
g_clear_object (&priv->current_cancellable);
cancellation_reason = g_steal_pointer (&priv->current_cancellation_reason);
fpi_device_update_temp (data->device, FALSE);
@@ -870,6 +877,8 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
g_object_notify (G_OBJECT (data->device), "open");
}
/* TODO: Port/use the cancellation mechanism for device removal! */
/* Return FP_DEVICE_ERROR_REMOVED if the device is removed,
* with the exception of a successful open, which is an odd corner case. */
if (priv->is_removed &&
@@ -884,6 +893,15 @@ fp_device_task_return_in_idle_cb (gpointer user_data)
return G_SOURCE_REMOVE;
}
/* Return internal cancellation reason if we have one.
* Note that an external cancellation always returns G_IO_ERROR_CANCELLED */
if (cancellation_reason)
{
g_task_return_error (task, g_steal_pointer (&cancellation_reason));
return G_SOURCE_REMOVE;
}
switch (data->type)
{
case FP_DEVICE_TASK_RETURN_INT: