diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2024-05-10 13:51:13 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2024-05-13 09:13:33 +0000 |
commit | 21998a7b3ef87de7731e18c9df4b7bf438ca3381 (patch) | |
tree | 59b5c06e532af2739fce3b4919d5541ffb5438ac /src/mm-plugin-manager.c | |
parent | 0bb31c3e8be2535116348b61fbf0dd2c0e46409b (diff) |
plugin-manager: ensure DeviceContext is valid during the whole cancellation procedure
Diffstat (limited to 'src/mm-plugin-manager.c')
-rw-r--r-- | src/mm-plugin-manager.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/src/mm-plugin-manager.c b/src/mm-plugin-manager.c index bfd6ceab..35c090b9 100644 --- a/src/mm-plugin-manager.c +++ b/src/mm-plugin-manager.c @@ -147,6 +147,8 @@ static void device_context_unref (DeviceContext *device_context); static PortContext *port_context_ref (PortContext *port_context); static void port_context_unref (PortContext *port_context); +G_DEFINE_AUTOPTR_CLEANUP_FUNC (DeviceContext, device_context_unref) + typedef struct { MMPluginManager *self; DeviceContext *device_context; @@ -1328,9 +1330,17 @@ device_context_port_added (MMPluginManager *self, } static gboolean -device_context_cancel (DeviceContext *device_context) +device_context_cancel (DeviceContext *_device_context) { - MMPluginManager *self; + g_autoptr(DeviceContext) device_context = NULL; + MMPluginManager *self; + + /* The device context cancellation operation will also independently request cancellation + * of each port context. Depending on the probing task of the port, this may be completed + * asynchronously or in-place. Therefore we need to consider the case where the last port + * context cancellation also completes the device context operation in-place, so we must + * ensure the DeviceContext is valid throughout the whole method. */ + device_context = device_context_ref (_device_context); /* If cancelled already, do nothing */ if (g_cancellable_is_cancelled (device_context->cancellable)) @@ -1353,7 +1363,6 @@ device_context_cancel (DeviceContext *device_context) /* Cancel all ongoing port contexts, if they're not already cancelled */ if (device_context->port_contexts) { g_assert (!device_context->wait_port_contexts); - /* Request cancellation, will be completed asynchronously */ g_list_foreach (device_context->port_contexts, (GFunc) port_context_cancel, NULL); } @@ -1371,9 +1380,11 @@ device_context_cancel (DeviceContext *device_context) device_context->extra_probing_time_id = 0; } - /* Wakeup the device context logic. If we were still waiting for the - * min probing time, this will complete the device context. */ - device_context_continue (device_context); + /* If the device context task is not yet completed, wakeup the device context + * logic. If we were still waiting for the min probing time, this will complete + * the device context. */ + if (device_context->task) + device_context_continue (device_context); return TRUE; } |