[mutter] core/selection: Cancel selection transfer requests after a timeout
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] core/selection: Cancel selection transfer requests after a timeout
- Date: Wed, 28 Jul 2021 15:50:01 +0000 (UTC)
commit 537e2dfafe3f03b2c55090c3fee714e985a744d9
Author: Pascal Nowack <Pascal Nowack gmx de>
Date: Thu Jun 24 05:44:22 2021 +0200
core/selection: Cancel selection transfer requests after a timeout
When a selection owner advertises a mime type, but does not provide the
content upon a request for the mime type content, the requesting side
might wait indefinitely on the content.
To avoid this situation, add a timeout source, which will cancel the
selection transfer request after a certain timeout (15 seconds) passed.
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1874>
src/core/meta-selection.c | 76 ++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 72 insertions(+), 4 deletions(-)
---
diff --git a/src/core/meta-selection.c b/src/core/meta-selection.c
index 4e42e59a9e..76c3420201 100644
--- a/src/core/meta-selection.c
+++ b/src/core/meta-selection.c
@@ -39,6 +39,10 @@ struct TransferRequest
GInputStream *istream;
GOutputStream *ostream;
gssize len;
+ GSource *timeout_source;
+ GCancellable *cancellable;
+ GCancellable *external_cancellable;
+ gulong cancellable_signal_handler;
};
enum
@@ -174,10 +178,39 @@ meta_selection_get_mimetypes (MetaSelection *selection,
return meta_selection_source_get_mimetypes (selection->owners[selection_type]);
}
+static gboolean
+cancel_transfer_request (gpointer user_data)
+{
+ TransferRequest *request = user_data;
+
+ g_cancellable_cancel (request->cancellable);
+ if (request->cancellable_signal_handler)
+ {
+ g_assert (request->external_cancellable);
+ g_cancellable_disconnect (request->external_cancellable,
+ request->cancellable_signal_handler);
+ request->cancellable_signal_handler = 0;
+ g_object_unref (request->external_cancellable);
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+on_external_cancellable_cancelled (GCancellable *external_cancellable,
+ TransferRequest *request)
+{
+ g_cancellable_cancel (request->cancellable);
+
+ g_source_destroy (request->timeout_source);
+ g_clear_pointer (&request->timeout_source, g_source_unref);
+}
+
static TransferRequest *
transfer_request_new (GOutputStream *ostream,
MetaSelectionType selection_type,
- gssize len)
+ ssize_t len,
+ GCancellable *external_cancellable)
{
TransferRequest *request;
@@ -185,12 +218,44 @@ transfer_request_new (GOutputStream *ostream,
request->ostream = g_object_ref (ostream);
request->selection_type = selection_type;
request->len = len;
+ request->cancellable = g_cancellable_new ();
+ request->timeout_source = g_timeout_source_new_seconds (15);
+
+ g_source_set_callback (request->timeout_source, cancel_transfer_request,
+ request, NULL);
+ g_source_attach (request->timeout_source, NULL);
+
+ if (external_cancellable)
+ {
+ request->external_cancellable = g_object_ref (external_cancellable);
+ request->cancellable_signal_handler =
+ g_cancellable_connect (external_cancellable,
+ G_CALLBACK (on_external_cancellable_cancelled),
+ request, NULL);
+ }
+
return request;
}
static void
transfer_request_free (TransferRequest *request)
{
+ if (request->cancellable_signal_handler)
+ {
+ g_assert (request->external_cancellable);
+ g_cancellable_disconnect (request->external_cancellable,
+ request->cancellable_signal_handler);
+ request->cancellable_signal_handler = 0;
+ g_object_unref (request->external_cancellable);
+ }
+
+ if (request->timeout_source)
+ {
+ g_source_destroy (request->timeout_source);
+ g_clear_pointer (&request->timeout_source, g_source_unref);
+ }
+
+ g_clear_object (&request->cancellable);
g_clear_object (&request->istream);
g_clear_object (&request->ostream);
g_free (request);
@@ -362,6 +427,7 @@ meta_selection_transfer_async (MetaSelection *selection,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ TransferRequest *transfer_request;
GTask *task;
g_return_if_fail (META_IS_SELECTION (selection));
@@ -372,12 +438,14 @@ meta_selection_transfer_async (MetaSelection *selection,
task = g_task_new (selection, cancellable, callback, user_data);
g_task_set_source_tag (task, meta_selection_transfer_async);
- g_task_set_task_data (task,
- transfer_request_new (output, selection_type, size),
+ transfer_request = transfer_request_new (output, selection_type, size,
+ cancellable);
+
+ g_task_set_task_data (task, transfer_request,
(GDestroyNotify) transfer_request_free);
meta_selection_source_read_async (selection->owners[selection_type],
mimetype,
- cancellable,
+ transfer_request->cancellable,
(GAsyncReadyCallback) source_read_cb,
task);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]