f87237
commit 164c03d33bd9d58844921888560baf3f156a1f05
f87237
Author: Christophe Fergeau <cfergeau@redhat.com>
f87237
Date:   Mon Sep 10 12:17:07 2012 +0200
f87237
f87237
    Fix unwanted closing of libvirt client connection
f87237
    
f87237
    e5a1bee07 introduced a regression in Boxes: when Boxes is left idle
f87237
    (it's still doing some libvirt calls in the background), the
f87237
    libvirt connection gets closed after a few minutes. What happens is
f87237
    that this code in virNetClientIOHandleOutput gets triggered:
f87237
    
f87237
    if (!thecall)
f87237
        return -1; /* Shouldn't happen, but you never know... */
f87237
    
f87237
    and after the changes in e5a1bee07, this causes the libvirt connection
f87237
    to be closed.
f87237
    
f87237
    Upon further investigation, what happens is that
f87237
    virNetClientIOHandleOutput is called from gvir_event_handle_dispatch
f87237
    in libvirt-glib, which is triggered because the client fd became
f87237
    writable. However, between the times gvir_event_handle_dispatch
f87237
    is called, and the time the client lock is grabbed and
f87237
    virNetClientIOHandleOutput is called, another thread runs and
f87237
    completes the current call. 'thecall' is then NULL when the first
f87237
    thread gets to run virNetClientIOHandleOutput.
f87237
    
f87237
    After describing this situation on IRC, danpb suggested this:
f87237
    
f87237
    11:37 < danpb> In that case I think the correct thing would be to change
f87237
                   'return -1' above to 'return 0' since that's not actually an
f87237
                   error - its a rare, but expected event
f87237
    
f87237
    which is what this patch is doing. I've tested it against master
f87237
    libvirt, and I didn't get disconnected in ~10 minutes while this
f87237
    happens in less than 5 minutes without this patch.
f87237
f87237
diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c
f87237
index 43a9814..727ed67 100644
f87237
--- a/src/rpc/virnetclient.c
f87237
+++ b/src/rpc/virnetclient.c
f87237
@@ -1205,7 +1205,10 @@ virNetClientIOHandleOutput(virNetClientPtr client)
f87237
         thecall = thecall->next;
f87237
 
f87237
     if (!thecall)
f87237
-        return -1; /* Shouldn't happen, but you never know... */
f87237
+        return 0; /* This can happen if another thread raced with us and
f87237
+                   * completed the call between the time this thread woke
f87237
+                   * up from poll()ing and the time we locked the client
f87237
+                   */
f87237
 
f87237
     while (thecall) {
f87237
         ssize_t ret = virNetClientIOWriteMessage(client, thecall);