diff options
author | Michael Catanzaro <mcatanzaro@redhat.com> | 2023-04-25 19:17:22 -0500 |
---|---|---|
committer | Michael Catanzaro <mcatanzaro@redhat.com> | 2023-04-27 09:20:48 -0500 |
commit | 0e205fce5fbfa8f2c6f6ac0acc890311ff333d04 (patch) | |
tree | 5024eb2e234f1d10d72cfa6265f7f5d31e7fbd54 /libsecret/secret-file-backend.c | |
parent | ecb788d44e5c4f01234b7b02141c2779373957c5 (diff) | |
download | libsecret-mcatanzaro/cancellable-deadlock.tar.gz |
file-backend: avoid deadlock when portal op is canceledmcatanzaro/cancellable-deadlock
Calling g_cancellable_disconnect() inside a cancelled handler is a
guaranteed deadlock. Cancellables should only be canceled once, so we
don't need to worry about a second cancellation occurring. I think it's
sufficent to disconnect when the InitClosure is freed.
Fixes #86
Diffstat (limited to 'libsecret/secret-file-backend.c')
-rw-r--r-- | libsecret/secret-file-backend.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/libsecret/secret-file-backend.c b/libsecret/secret-file-backend.c index 12738df..dd18a5b 100644 --- a/libsecret/secret-file-backend.c +++ b/libsecret/secret-file-backend.c @@ -206,6 +206,7 @@ typedef struct { GDBusConnection *connection; gchar *request_path; guint portal_signal_id; + GCancellable *cancellable; gulong cancellable_signal_id; } InitClosure; @@ -218,6 +219,14 @@ init_closure_free (gpointer data) g_clear_pointer (&init->buffer, egg_secure_free); g_clear_object (&init->connection); g_clear_pointer (&init->request_path, g_free); + if (init->cancellable_signal_id) { + g_cancellable_disconnect (init->cancellable, init->cancellable_signal_id); + init->cancellable_signal_id = 0; + } + /* Note: do not cancel the cancellable here! That's for the API user to + * do. We're just keeping track of it here so we can disconnect. + */ + g_clear_object (&init->cancellable); g_free (init); } @@ -352,9 +361,6 @@ on_portal_cancel (GCancellable *cancellable, cancellable, on_portal_request_close, task); - - g_cancellable_disconnect (cancellable, init->cancellable_signal_id); - init->cancellable_signal_id = 0; } static void @@ -575,6 +581,7 @@ secret_file_backend_real_init_async (GAsyncInitable *initable, init = g_new0 (InitClosure, 1); init->io_priority = io_priority; init->file = file; + init->cancellable = g_object_ref (cancellable); g_task_set_task_data (task, init, init_closure_free); g_bus_get (G_BUS_TYPE_SESSION, cancellable, on_bus_get, task); } else { |