160 lines
5.7 KiB
Diff
160 lines
5.7 KiB
Diff
From 2ecbf6d74637508203290c0e324d736de10a9174 Mon Sep 17 00:00:00 2001
|
|
From: Carlos Garnacho <carlosg@gnome.org>
|
|
Date: Mon, 24 Feb 2020 15:33:08 +0100
|
|
Subject: [PATCH 37/48] x11: Handle windowing errors while writing selection
|
|
INCR data
|
|
|
|
This error was just logged but not raised. Do as the code comment said
|
|
and raise a pipe error at that moment, and for subsequent operations
|
|
on the output stream (although none besides close() should be expected
|
|
after propagating the error properly).
|
|
|
|
Related: https://gitlab.gnome.org/GNOME/mutter/issues/1065
|
|
---
|
|
src/x11/meta-x11-selection-output-stream.c | 62 +++++++++++++++++++---
|
|
1 file changed, 56 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/src/x11/meta-x11-selection-output-stream.c b/src/x11/meta-x11-selection-output-stream.c
|
|
index 1883bc92a..f51dbc4c3 100644
|
|
--- a/src/x11/meta-x11-selection-output-stream.c
|
|
+++ b/src/x11/meta-x11-selection-output-stream.c
|
|
@@ -53,6 +53,7 @@ struct _MetaX11SelectionOutputStreamPrivate
|
|
|
|
guint incr : 1;
|
|
guint delete_pending : 1;
|
|
+ guint pipe_error : 1;
|
|
};
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaX11SelectionOutputStream,
|
|
@@ -167,6 +168,25 @@ get_element_size (int format)
|
|
}
|
|
}
|
|
|
|
+static gboolean
|
|
+meta_x11_selection_output_stream_check_pipe (MetaX11SelectionOutputStream *stream,
|
|
+ GError **error)
|
|
+{
|
|
+ MetaX11SelectionOutputStreamPrivate *priv =
|
|
+ meta_x11_selection_output_stream_get_instance_private (stream);
|
|
+
|
|
+ if (priv->pipe_error)
|
|
+ {
|
|
+ g_set_error (error,
|
|
+ G_IO_ERROR,
|
|
+ G_IO_ERROR_BROKEN_PIPE,
|
|
+ "Connection with client was broken");
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
static void
|
|
meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *stream)
|
|
{
|
|
@@ -174,6 +194,7 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
|
meta_x11_selection_output_stream_get_instance_private (stream);
|
|
Display *xdisplay;
|
|
size_t element_size, n_elements;
|
|
+ int error_code;
|
|
|
|
g_assert (!priv->delete_pending);
|
|
|
|
@@ -230,18 +251,28 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
|
g_cond_broadcast (&priv->cond);
|
|
g_mutex_unlock (&priv->mutex);
|
|
|
|
- /* XXX: handle failure here and report EPIPE for future operations on the stream? */
|
|
- if (meta_x11_error_trap_pop_with_return (priv->x11_display))
|
|
- g_warning ("Failed to flush selection output stream");
|
|
+ error_code = meta_x11_error_trap_pop_with_return (priv->x11_display);
|
|
|
|
- if (priv->pending_task)
|
|
+ if (error_code != Success)
|
|
+ {
|
|
+ char error_str[100];
|
|
+
|
|
+ XGetErrorText (xdisplay, error_code, error_str, sizeof (error_str));
|
|
+ g_task_return_new_error (priv->pending_task,
|
|
+ G_IO_ERROR,
|
|
+ G_IO_ERROR_BROKEN_PIPE,
|
|
+ "Failed to flush selection output stream: %s",
|
|
+ error_str);
|
|
+ g_clear_object (&priv->pending_task);
|
|
+ priv->pipe_error = TRUE;
|
|
+ }
|
|
+ else if (priv->pending_task)
|
|
{
|
|
size_t result;
|
|
|
|
result = GPOINTER_TO_SIZE (g_task_get_task_data (priv->pending_task));
|
|
g_task_return_int (priv->pending_task, result);
|
|
- g_object_unref (priv->pending_task);
|
|
- priv->pending_task = NULL;
|
|
+ g_clear_object (&priv->pending_task);
|
|
}
|
|
}
|
|
|
|
@@ -270,6 +301,9 @@ meta_x11_selection_output_stream_write (GOutputStream *output_stream,
|
|
MetaX11SelectionOutputStreamPrivate *priv =
|
|
meta_x11_selection_output_stream_get_instance_private (stream);
|
|
|
|
+ if (!meta_x11_selection_output_stream_check_pipe (stream, error))
|
|
+ return -1;
|
|
+
|
|
g_mutex_lock (&priv->mutex);
|
|
g_byte_array_append (priv->data, buffer, count);
|
|
g_mutex_unlock (&priv->mutex);
|
|
@@ -297,12 +331,19 @@ meta_x11_selection_output_stream_write_async (GOutputStream *output_stream
|
|
META_X11_SELECTION_OUTPUT_STREAM (output_stream);
|
|
MetaX11SelectionOutputStreamPrivate *priv =
|
|
meta_x11_selection_output_stream_get_instance_private (stream);
|
|
+ GError *error = NULL;
|
|
GTask *task;
|
|
|
|
task = g_task_new (stream, cancellable, callback, user_data);
|
|
g_task_set_source_tag (task, meta_x11_selection_output_stream_write_async);
|
|
g_task_set_priority (task, io_priority);
|
|
|
|
+ if (!meta_x11_selection_output_stream_check_pipe (stream, &error))
|
|
+ {
|
|
+ g_task_return_error (task, error);
|
|
+ return;
|
|
+ }
|
|
+
|
|
g_mutex_lock (&priv->mutex);
|
|
g_byte_array_append (priv->data, buffer, count);
|
|
g_mutex_unlock (&priv->mutex);
|
|
@@ -369,6 +410,8 @@ meta_x11_selection_output_stream_flush (GOutputStream *output_stream,
|
|
MetaX11SelectionOutputStreamPrivate *priv =
|
|
meta_x11_selection_output_stream_get_instance_private (stream);
|
|
|
|
+ if (!meta_x11_selection_output_stream_check_pipe (stream, error))
|
|
+ return FALSE;
|
|
if (!meta_x11_selection_output_request_flush (stream))
|
|
return TRUE;
|
|
|
|
@@ -394,12 +437,19 @@ meta_x11_selection_output_stream_flush_async (GOutputStream *output_stream
|
|
META_X11_SELECTION_OUTPUT_STREAM (output_stream);
|
|
MetaX11SelectionOutputStreamPrivate *priv =
|
|
meta_x11_selection_output_stream_get_instance_private (stream);
|
|
+ GError *error = NULL;
|
|
GTask *task;
|
|
|
|
task = g_task_new (stream, cancellable, callback, user_data);
|
|
g_task_set_source_tag (task, meta_x11_selection_output_stream_flush_async);
|
|
g_task_set_priority (task, io_priority);
|
|
|
|
+ if (!meta_x11_selection_output_stream_check_pipe (stream, &error))
|
|
+ {
|
|
+ g_task_return_error (task, error);
|
|
+ return;
|
|
+ }
|
|
+
|
|
if (!meta_x11_selection_output_stream_can_flush (stream))
|
|
{
|
|
if (meta_x11_selection_output_request_flush (stream))
|
|
--
|
|
2.26.0.rc2
|
|
|