From c41657bc4faf790a0f14e634490b7fffa844e0b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 8 Nov 2021 10:44:17 +0100 Subject: [PATCH] wayland/activation: Remove token from hash table on timeout When an activation times out, we'll be signalled two signals on the startup sequence object: "timeout", and "complete". Normally, the "complete" signal is emitted when a startup sequence is completed succesfully by it being used for activation, and in this case, the xdg_activation implementation should remove the sequence from the startup notification machinery. However, in the timeout case, we should not remove it, as the startup notification machinery itself will deal with this. If we would, we'd end up with use-after-free issues, as the sequence would be finalized when removed the first time. To avoid this, just clean up the Wayland side in the "timeout" signal handler, leaving the "complete" signal handler early out if it was already handled by it. This avoids crashes like: 0) g_type_check_instance (type_instance=type_instance@entry=0xdd6740) 1) g_signal_handlers_disconnect_matched (instance=0xdd6740, ...) 2) meta_startup_notification_remove_sequence (sn=0x4cc890, seq=0xdd6740) at ../src/core/startup-notification.c:544 3) startup_sequence_timeout (data=0x4cc890, ...) at ../src/core/startup-notification.c:504 4) g_timeout_dispatch (...) at ../glib/gmain.c:4933 Part-of: --- src/wayland/meta-wayland-activation.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/wayland/meta-wayland-activation.c b/src/wayland/meta-wayland-activation.c index 07bc1adaa..20fb1f1e9 100644 --- a/src/wayland/meta-wayland-activation.c +++ b/src/wayland/meta-wayland-activation.c @@ -51,6 +51,7 @@ struct _MetaXdgActivationToken char *token; uint32_t serial; gulong sequence_complete_id; + gulong sequence_timeout_id; gboolean committed; }; @@ -102,11 +103,23 @@ sequence_complete_cb (MetaStartupSequence *sequence, MetaWaylandActivation *activation = token->activation; MetaDisplay *display = meta_get_display (); + if (!g_hash_table_contains (activation->tokens, token->token)) + return; + meta_startup_notification_remove_sequence (display->startup_notification, sequence); g_hash_table_remove (activation->tokens, token->token); } +static void +sequence_timeout_cb (MetaStartupSequence *sequence, + MetaXdgActivationToken *token) +{ + MetaWaylandActivation *activation = token->activation; + + g_hash_table_remove (activation->tokens, token->token); +} + static char * create_startup_token (MetaWaylandActivation *activation, MetaDisplay *display) @@ -158,6 +171,11 @@ token_commit (struct wl_client *client, "complete", G_CALLBACK (sequence_complete_cb), token); + token->sequence_timeout_id = + g_signal_connect (token->sequence, + "timeout", + G_CALLBACK (sequence_timeout_cb), + token); meta_startup_notification_add_sequence (display->startup_notification, token->sequence); @@ -188,6 +206,8 @@ meta_xdg_activation_token_free (MetaXdgActivationToken *token) { g_clear_signal_handler (&token->sequence_complete_id, token->sequence); + g_clear_signal_handler (&token->sequence_timeout_id, + token->sequence); g_clear_object (&token->sequence); }