gdbus: delay closing stream after read finish
authorMarc-André Lureau <marcandre.lureau@gmail.com>
Thu, 12 Feb 2015 21:29:36 +0000 (22:29 +0100)
committerRyan Lortie <desrt@desrt.ca>
Tue, 17 Feb 2015 21:16:52 +0000 (16:16 -0500)
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

index 54659c1e27d54330e5668f507a8d4ca382dfd3aa..64bf935fd4e9790be5ac649529e4bad35ba75531 100644 (file)
@@ -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