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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2081>
This commit is contained in:
Jonas Ådahl 2021-11-08 10:44:17 +01:00
parent a2cf75ccd5
commit c41657bc4f

View File

@ -51,6 +51,7 @@ struct _MetaXdgActivationToken
char *token; char *token;
uint32_t serial; uint32_t serial;
gulong sequence_complete_id; gulong sequence_complete_id;
gulong sequence_timeout_id;
gboolean committed; gboolean committed;
}; };
@ -102,11 +103,23 @@ sequence_complete_cb (MetaStartupSequence *sequence,
MetaWaylandActivation *activation = token->activation; MetaWaylandActivation *activation = token->activation;
MetaDisplay *display = meta_get_display (); MetaDisplay *display = meta_get_display ();
if (!g_hash_table_contains (activation->tokens, token->token))
return;
meta_startup_notification_remove_sequence (display->startup_notification, meta_startup_notification_remove_sequence (display->startup_notification,
sequence); sequence);
g_hash_table_remove (activation->tokens, token->token); 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 * static char *
create_startup_token (MetaWaylandActivation *activation, create_startup_token (MetaWaylandActivation *activation,
MetaDisplay *display) MetaDisplay *display)
@ -158,6 +171,11 @@ token_commit (struct wl_client *client,
"complete", "complete",
G_CALLBACK (sequence_complete_cb), G_CALLBACK (sequence_complete_cb),
token); 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, meta_startup_notification_add_sequence (display->startup_notification,
token->sequence); token->sequence);
@ -188,6 +206,8 @@ meta_xdg_activation_token_free (MetaXdgActivationToken *token)
{ {
g_clear_signal_handler (&token->sequence_complete_id, g_clear_signal_handler (&token->sequence_complete_id,
token->sequence); token->sequence);
g_clear_signal_handler (&token->sequence_timeout_id,
token->sequence);
g_clear_object (&token->sequence); g_clear_object (&token->sequence);
} }