From 512e9b3b34d067ae4685143eb0c5f7969c6fd1e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 12 Feb 2015 22:29:36 +0100 Subject: [PATCH] gdbus: delay closing stream after read finish Closing the stream on the writing side my race with a pending read. This patch ensures that closing is delayed after reading is finished. https://bugzilla.gnome.org/show_bug.cgi?id=743990 --- gio/gdbusprivate.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c index 54659c1e2..64bf935fd 100644 --- a/gio/gdbusprivate.c +++ b/gio/gdbusprivate.c @@ -52,6 +52,7 @@ #include "glibintl.h" static gboolean _g_dbus_worker_do_initial_read (gpointer data); +static void schedule_pending_close (GDBusWorker *worker); /* ---------------------------------------------------------------------------------------------------- */ @@ -817,6 +818,9 @@ _g_dbus_worker_do_read_cb (GInputStream *input_stream, /* gives up the reference acquired when calling g_input_stream_read_async() */ _g_dbus_worker_unref (worker); + + /* check if there is any pending close */ + schedule_pending_close (worker); } /* called in private thread shared by all GDBusConnection instances (with read-lock held) */ @@ -1445,12 +1449,17 @@ continue_writing (GDBusWorker *worker) /* if we want to close the connection, that takes precedence */ if (worker->pending_close_attempts != NULL) { - worker->close_expected = TRUE; - worker->output_pending = PENDING_CLOSE; + GInputStream *input = g_io_stream_get_input_stream (worker->stream); - g_io_stream_close_async (worker->stream, G_PRIORITY_DEFAULT, - NULL, iostream_close_cb, - _g_dbus_worker_ref (worker)); + if (!g_input_stream_has_pending (input)) + { + worker->close_expected = TRUE; + worker->output_pending = PENDING_CLOSE; + + g_io_stream_close_async (worker->stream, G_PRIORITY_DEFAULT, + NULL, iostream_close_cb, + _g_dbus_worker_ref (worker)); + } } else { @@ -1603,6 +1612,15 @@ schedule_writing_unlocked (GDBusWorker *worker, } } +static void +schedule_pending_close (GDBusWorker *worker) +{ + if (!worker->pending_close_attempts) + return; + + schedule_writing_unlocked (worker, NULL, NULL, NULL); +} + /* ---------------------------------------------------------------------------------------------------- */ /* can be called from any thread - steals blob