Libvirtd daemon cleanup is not correct in case there are admin server
clients connected at the moment libvirtd exits. The reason is
that there is cyclic dependency: daemon holds references to its
network servers, networks servers hold references to its clients,
admin server clients hold refs to daemon. These refs are kept until
holder object dispose thus the above objects are never get disposed.
Let's drop references to severs in daemon object at appropriate moment
on cleanup procedure to break the cycle.
The caller should keep references to servers by itself. Otherwise
dropping refences can cause synchronous servers cleanup which
can cause deadlock (server cleanup blocks until workers are
finished and workers can call daemon functions which will try
to get daemon lock). Other option is to make list cleanup
via temporary list copy.
---
daemon/libvirtd.c | 3 +++
src/rpc/virnetdaemon.c | 1 +
2 files changed, 4 insertions(+)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index 95c1b1c..7fac7b2 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -1628,6 +1628,9 @@ int main(int argc, char **argv) {
virObjectUnref(qemuProgram);
virObjectUnref(adminProgram);
virNetDaemonClose(dmn);
+ /* we need to keep servers references up to here
+ so that above function will not cause servers cleanup
+ which can deadlock */
virObjectUnref(dmn);
virObjectUnref(srv);
virObjectUnref(srvAdm);
diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c
index dcc89fa..c6c6522 100644
--- a/src/rpc/virnetdaemon.c
+++ b/src/rpc/virnetdaemon.c
@@ -861,6 +861,7 @@ virNetDaemonClose(virNetDaemonPtr dmn)
virObjectLock(dmn);
virHashForEach(dmn->servers, daemonServerClose, NULL);
+ virHashRemoveAll(dmn->servers);
virObjectUnlock(dmn);
}
--
1.8.3.1