agent: Fix a potential re-entrancy situation
authorPhilip Withnall <philip.withnall@collabora.co.uk>
Tue, 4 Mar 2014 13:48:03 +0000 (13:48 +0000)
committerOlivier Crête <olivier.crete@collabora.com>
Tue, 4 Mar 2014 20:47:25 +0000 (15:47 -0500)
If we emit signals from component_io_cb() in the middle of a read, it’s
possible that one of those signals will be picked up by the client to
perform another read. A likely candidate (and what was triggering the
re-entrancy here) would be component-state-changed. Since signals are
emitted synchronously, the second read would being inside the first, and
trigger the anti-re-entrancy assertion.

agent/agent.c

index 689a2f6..3c22959 100644 (file)
@@ -3876,8 +3876,14 @@ component_io_cb (GSocket *socket, GIOCondition condition, gpointer user_data)
   }
 
 done:
-
-  agent_unlock_and_emit (agent);
+  /* If we’re in the middle of a read, don’t emit any signals, or we could cause
+   * re-entrancy by (e.g.) emitting component-state-changed and having the
+   * client perform a read. */
+  if (component->n_recv_messages == 0 && component->recv_messages == NULL) {
+    agent_unlock_and_emit (agent);
+  } else {
+    agent_unlock ();
+  }
 
   g_object_unref (agent);