Merge branch 'wip/otte/for-main' into 'main'
x11: Fix a deadlock in INCR transfers See merge request GNOME/gtk!4242
This commit is contained in:
@@ -76,11 +76,30 @@ print_atoms (GdkX11Clipboard *cb,
|
||||
});
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_clipboard_default_output_closed (GObject *stream,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_output_stream_close_finish (G_OUTPUT_STREAM (stream), result, &error))
|
||||
{
|
||||
GDK_NOTE (CLIPBOARD,
|
||||
g_printerr ("-------: failed to close stream: %s\n",
|
||||
error->message));
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_clipboard_default_output_done (GObject *clipboard,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GOutputStream *stream = user_data;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gdk_clipboard_write_finish (GDK_CLIPBOARD (clipboard), result, &error))
|
||||
@@ -90,6 +109,12 @@ gdk_x11_clipboard_default_output_done (GObject *clipboard,
|
||||
GDK_X11_CLIPBOARD (clipboard)->selection, error->message));
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_output_stream_close_async (stream,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
gdk_x11_clipboard_default_output_closed,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -103,8 +128,7 @@ gdk_x11_clipboard_default_output_handler (GOutputStream *stream,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
gdk_x11_clipboard_default_output_done,
|
||||
NULL);
|
||||
g_object_unref (stream);
|
||||
stream);
|
||||
}
|
||||
|
||||
static GInputStream *
|
||||
|
||||
@@ -1612,11 +1612,30 @@ gdk_x11_drag_set_hotspot (GdkDrag *drag,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_drag_default_output_closed (GObject *stream,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!g_output_stream_close_finish (G_OUTPUT_STREAM (stream), result, &error))
|
||||
{
|
||||
GDK_NOTE (DND,
|
||||
g_printerr ("failed to close stream: %s\n",
|
||||
error->message));
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_drag_default_output_done (GObject *drag,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GOutputStream *stream = user_data;
|
||||
GError *error = NULL;
|
||||
|
||||
if (!gdk_drag_write_finish (GDK_DRAG (drag), result, &error))
|
||||
@@ -1624,6 +1643,12 @@ gdk_x11_drag_default_output_done (GObject *drag,
|
||||
GDK_DISPLAY_NOTE (gdk_drag_get_display (GDK_DRAG (drag)), DND, g_printerr ("failed to write stream: %s\n", error->message));
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_output_stream_close_async (stream,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
gdk_x11_drag_default_output_closed,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1637,8 +1662,7 @@ gdk_x11_drag_default_output_handler (GOutputStream *stream,
|
||||
G_PRIORITY_DEFAULT,
|
||||
NULL,
|
||||
gdk_x11_drag_default_output_done,
|
||||
NULL);
|
||||
g_object_unref (stream);
|
||||
stream);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
||||
@@ -57,7 +57,8 @@ struct _GdkX11SelectionOutputStreamPrivate {
|
||||
GTask *pending_task;
|
||||
|
||||
guint incr : 1;
|
||||
guint delete_pending : 1;
|
||||
guint sent_end_of_stream : 1;
|
||||
guint delete_pending : 1; /* owns a reference */
|
||||
};
|
||||
|
||||
struct _GdkX11PendingSelectionNotify
|
||||
@@ -176,12 +177,16 @@ gdk_x11_selection_output_stream_needs_flush_unlocked (GdkX11SelectionOutputStrea
|
||||
{
|
||||
GdkX11SelectionOutputStreamPrivate *priv = gdk_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
if (priv->data->len == 0 && priv->notify == NULL)
|
||||
if (priv->sent_end_of_stream)
|
||||
return FALSE;
|
||||
|
||||
if (g_output_stream_is_closing (G_OUTPUT_STREAM (stream)))
|
||||
if (g_output_stream_is_closing (G_OUTPUT_STREAM (stream)) ||
|
||||
g_output_stream_is_closed (G_OUTPUT_STREAM (stream)))
|
||||
return TRUE;
|
||||
|
||||
if (priv->data->len == 0 && priv->notify == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (priv->flush_requested)
|
||||
return TRUE;
|
||||
|
||||
@@ -284,6 +289,8 @@ gdk_x11_selection_output_stream_perform_flush (GdkX11SelectionOutputStream *stre
|
||||
g_byte_array_remove_range (priv->data, 0, n_elements * element_size);
|
||||
if (priv->data->len < element_size)
|
||||
priv->flush_requested = FALSE;
|
||||
if (!priv->incr || n_elements == 0)
|
||||
priv->sent_end_of_stream = TRUE;
|
||||
}
|
||||
|
||||
if (priv->notify)
|
||||
@@ -292,6 +299,7 @@ gdk_x11_selection_output_stream_perform_flush (GdkX11SelectionOutputStream *stre
|
||||
priv->notify = NULL;
|
||||
}
|
||||
|
||||
g_object_ref (stream);
|
||||
priv->delete_pending = TRUE;
|
||||
g_cond_broadcast (&priv->cond);
|
||||
g_mutex_unlock (&priv->mutex);
|
||||
@@ -494,60 +502,6 @@ gdk_x11_selection_output_stream_flush_finish (GOutputStream *stream,
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_x11_selection_output_stream_invoke_close (gpointer stream)
|
||||
{
|
||||
GdkX11SelectionOutputStreamPrivate *priv = gdk_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
GDK_X11_DISPLAY (priv->display)->streams = g_slist_remove (GDK_X11_DISPLAY (priv->display)->streams, stream);
|
||||
g_signal_handlers_disconnect_by_func (priv->display,
|
||||
gdk_x11_selection_output_stream_xevent,
|
||||
stream);
|
||||
g_object_unref (stream);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_x11_selection_output_stream_close (GOutputStream *stream,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
g_main_context_invoke (NULL, gdk_x11_selection_output_stream_invoke_close, g_object_ref (stream));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_selection_output_stream_close_async (GOutputStream *stream,
|
||||
int io_priority,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (stream, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, gdk_x11_selection_output_stream_close_async);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
gdk_x11_selection_output_stream_invoke_close (stream);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_x11_selection_output_stream_close_finish (GOutputStream *stream,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
|
||||
g_return_val_if_fail (g_async_result_is_tagged (result, gdk_x11_selection_output_stream_close_async), FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_selection_output_stream_finalize (GObject *object)
|
||||
{
|
||||
@@ -557,6 +511,13 @@ gdk_x11_selection_output_stream_finalize (GObject *object)
|
||||
/* not sending a notify is terrible */
|
||||
g_assert (priv->notify == NULL);
|
||||
|
||||
GDK_DISPLAY_NOTE (priv->display, SELECTION, g_printerr ("%s:%s: finalizing\n",
|
||||
priv->selection, priv->target));
|
||||
GDK_X11_DISPLAY (priv->display)->streams = g_slist_remove (GDK_X11_DISPLAY (priv->display)->streams, stream);
|
||||
g_signal_handlers_disconnect_by_func (priv->display,
|
||||
gdk_x11_selection_output_stream_xevent,
|
||||
stream);
|
||||
|
||||
g_byte_array_unref (priv->data);
|
||||
g_cond_clear (&priv->cond);
|
||||
g_mutex_clear (&priv->mutex);
|
||||
@@ -579,14 +540,11 @@ gdk_x11_selection_output_stream_class_init (GdkX11SelectionOutputStreamClass *kl
|
||||
|
||||
output_stream_class->write_fn = gdk_x11_selection_output_stream_write;
|
||||
output_stream_class->flush = gdk_x11_selection_output_stream_flush;
|
||||
output_stream_class->close_fn = gdk_x11_selection_output_stream_close;
|
||||
|
||||
output_stream_class->write_async = gdk_x11_selection_output_stream_write_async;
|
||||
output_stream_class->write_finish = gdk_x11_selection_output_stream_write_finish;
|
||||
output_stream_class->flush_async = gdk_x11_selection_output_stream_flush_async;
|
||||
output_stream_class->flush_finish = gdk_x11_selection_output_stream_flush_finish;
|
||||
output_stream_class->close_async = gdk_x11_selection_output_stream_close_async;
|
||||
output_stream_class->close_finish = gdk_x11_selection_output_stream_close_finish;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -628,6 +586,7 @@ gdk_x11_selection_output_stream_xevent (GdkDisplay *display,
|
||||
if (gdk_x11_selection_output_stream_needs_flush (stream) &&
|
||||
gdk_x11_selection_output_stream_can_flush (stream))
|
||||
gdk_x11_selection_output_stream_perform_flush (stream);
|
||||
g_object_unref (stream); /* from unsetting the delete_pending */
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user