If the event loop is being processed in a background thread, then while
doing an RPC call, the event loop may get spurious wakeups due to the
POLLIN condition being satisfied by the incoming RPC reply. This will
cause the a-sync event handler to be unneccessarily run, and then block
the entire event loop due to it waitinf on the mutex for the call() method
to complete. Blocking the entire event loop is somewhat undesirable, so
we turn off the FD watches while in a call() an re-enable them after.
Daniel
diff --git a/src/remote_internal.c b/src/remote_internal.c
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -753,9 +753,7 @@ doRemoteOpen (virConnectPtr conn,
DEBUG0("Adding Handler for remote events");
/* Set up a callback to listen on the socket data */
if ((priv->watch = virEventAddHandle(priv->sock,
- VIR_EVENT_HANDLE_READABLE |
- VIR_EVENT_HANDLE_ERROR |
- VIR_EVENT_HANDLE_HANGUP,
+ VIR_EVENT_HANDLE_READABLE,
remoteDomainEventFired,
conn, NULL)) < 0) {
DEBUG0("virEventAddHandle failed: No addHandleImpl defined."
@@ -5588,11 +5586,11 @@ static int really_read (virConnectPtr co
* else Bad Things will happen in the XDR code.
*/
static int
-call (virConnectPtr conn, struct private_data *priv,
- int flags /* if we are in virConnectOpen */,
- int proc_nr,
- xdrproc_t args_filter, char *args,
- xdrproc_t ret_filter, char *ret)
+doCall (virConnectPtr conn, struct private_data *priv,
+ int flags /* if we are in virConnectOpen */,
+ int proc_nr,
+ xdrproc_t args_filter, char *args,
+ xdrproc_t ret_filter, char *ret)
{
char buffer[REMOTE_MESSAGE_MAX];
char buffer2[4];
@@ -5781,6 +5779,34 @@ retry_read:
xdr_destroy (&xdr);
return -1;
}
+}
+
+
+static int
+call (virConnectPtr conn, struct private_data *priv,
+ int flags /* if we are in virConnectOpen */,
+ int proc_nr,
+ xdrproc_t args_filter, char *args,
+ xdrproc_t ret_filter, char *ret)
+{
+ int rv;
+ /*
+ * Avoid needless wake-ups of the event loop in the
+ * case where this call is being made from a different
+ * thread than the event loop. These wake-ups would
+ * cause the event loop thread to be blocked on the
+ * mutex for the duration of the call
+ */
+ if (priv->watch >= 0)
+ virEventUpdateHandle(priv->watch, 0);
+
+ rv = doCall(conn, priv,flags, proc_nr,
+ args_filter, args,
+ ret_filter, ret);
+
+ if (priv->watch >= 0)
+ virEventUpdateHandle(priv->watch, VIR_EVENT_HANDLE_READABLE);
+ return rv;
}
static int
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|