]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Fix deadlock on libvirtd shutdown
authorJim Fehlig <jfehlig@suse.com>
Thu, 21 Jun 2012 15:21:44 +0000 (09:21 -0600)
committerJim Fehlig <jfehlig@suse.com>
Thu, 21 Jun 2012 17:38:51 +0000 (11:38 -0600)
When shutting down libvirtd, the virNetServer shutdown can deadlock
if there are in-flight jobs being handled by virNetServerHandleJob().
virNetServerFree() will acquire the virNetServer lock and call
virThreadPoolFree() to terminate the workers, waiting for the workers
to finish.  But in-flight workers will attempt to acquire the
virNetServer lock, resulting in deadlock.

Fix the deadlock by unlocking the virNetServer lock before calling
virThreadPoolFree().  This is safe since the virNetServerPtr object
is ref-counted and only decrementing the ref count needs to be
protected.  Additionally, there is no need to re-acquire the lock
after virThreadPoolFree() completes as all the workers have
terminated.

src/rpc/virnetserver.c

index ae19e84778de182817633bcc1a66c60b1fe6039c..9d71e53698b29ed7aec10c03fe41e65e39bc2d07 100644 (file)
@@ -766,10 +766,9 @@ void virNetServerFree(virNetServerPtr srv)
     virNetServerLock(srv);
     VIR_DEBUG("srv=%p refs=%d", srv, srv->refs);
     srv->refs--;
-    if (srv->refs > 0) {
-        virNetServerUnlock(srv);
+    virNetServerUnlock(srv);
+    if (srv->refs > 0)
         return;
-    }
 
     for (i = 0 ; i < srv->nservices ; i++)
         virNetServerServiceToggle(srv->services[i], false);
@@ -805,7 +804,6 @@ void virNetServerFree(virNetServerPtr srv)
     virNetServerMDNSFree(srv->mdns);
 #endif
 
-    virNetServerUnlock(srv);
     virMutexDestroy(&srv->lock);
     VIR_FREE(srv);
 }