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
This commit is contained in:
parent
a13d60aae5
commit
2ecbf6d746
@ -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))
|
||||
|
Loading…
Reference in New Issue
Block a user