[gtk/wip/otte/clipboard: 13179/13183] x11: Don't deadlock when flush()ing from the main loop
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/clipboard: 13179/13183] x11: Don't deadlock when flush()ing from the main loop
- Date: Fri, 18 Sep 2020 04:55:46 +0000 (UTC)
commit 2489e0047a514fd2311bcb7c572a619ea409d951
Author: Benjamin Otte <otte redhat com>
Date: Thu Sep 17 16:15:19 2020 +0200
x11: Don't deadlock when flush()ing from the main loop
Instead, emit a warning that it's not supported and don't flush
anything.
Of course, this usually happens on close(), so we are now dropping the
data, which is still unfortunate, but a step up from deadlocking.
gdk/x11/gdkselectionoutputstream-x11.c | 29 +++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)
---
diff --git a/gdk/x11/gdkselectionoutputstream-x11.c b/gdk/x11/gdkselectionoutputstream-x11.c
index b9aad4c3f3..d052982c59 100644
--- a/gdk/x11/gdkselectionoutputstream-x11.c
+++ b/gdk/x11/gdkselectionoutputstream-x11.c
@@ -439,8 +439,33 @@ gdk_x11_selection_output_stream_flush (GOutputStream *output_stream,
g_main_context_invoke (NULL, gdk_x11_selection_output_stream_invoke_flush, stream);
g_mutex_lock (&priv->mutex);
- if (gdk_x11_selection_output_stream_needs_flush_unlocked (stream))
- g_cond_wait (&priv->cond, &priv->mutex);
+ while (gdk_x11_selection_output_stream_needs_flush_unlocked (stream))
+ {
+ /* We cannot do sync flushes as we need to run the main loop to do the flushing. */
+ if (g_main_context_is_owner (NULL))
+ {
+#define ERROR_MESSAGE \
+ "Synchronous flushing of X11 data streams from the main loop is not possible.\n" \
+ "Use g_output_stream_flush_async() or g_output_stream_close_async() to avoid data loss."
+
+ g_mutex_unlock (&priv->mutex);
+
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, ERROR_MESSAGE);
+
+ /* We also warn here instead of just erroring out because this happens when people forget
+ * to explicitly close a data stream and just unref() it as dispose() runs a sync close()
+ * which does a sync flush().
+ */
+ g_warning (ERROR_MESSAGE);
+
+ return FALSE;
+#undef ERROR_MESSAGE
+ }
+ else
+ {
+ g_cond_wait (&priv->cond, &priv->mutex);
+ }
+ }
g_mutex_unlock (&priv->mutex);
return TRUE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]