[mutter/wip/carlosg/selection-epipe-on-x-error: 9/9] x11: Handle windowing errors while writing selection INCR data
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/carlosg/selection-epipe-on-x-error: 9/9] x11: Handle windowing errors while writing selection INCR data
- Date: Fri, 20 Mar 2020 15:15:43 +0000 (UTC)
commit 2ecbf6d74637508203290c0e324d736de10a9174
Author: Carlos Garnacho <carlosg gnome org>
Date: Mon Feb 24 15:33:08 2020 +0100
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))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]