When virNetDaemonQuit is called from libvirtd's shutdown
handler (daemonShutdownHandler) we need to perform the quit
in multiple steps. The first part is to "request" the quit
and notify the NetServer's of the impending quit which causes
the NetServers to Drain their pending queue and tell workers
to quit and the second is wait for any currently running
worker jobs to complete. Once the workers are complete, then
we can cause the quit to occur.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/rpc/virnetdaemon.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c
index e5b376ced..6aee712a5 100644
--- a/src/rpc/virnetdaemon.c
+++ b/src/rpc/virnetdaemon.c
@@ -73,6 +73,7 @@ struct _virNetDaemon {
virHashTablePtr servers;
virJSONValuePtr srvObject;
+ bool quitRequested;
bool quit;
unsigned int autoShutdownTimeout;
@@ -779,6 +780,32 @@ daemonServerProcessClients(void *payload,
return 0;
}
+
+static int
+daemonServerWorkerCount(void *payload,
+ const void *key ATTRIBUTE_UNUSED,
+ void *opaque)
+{
+ size_t *workerCount = opaque;
+ virNetServerPtr srv = payload;
+
+ *workerCount += virNetServerWorkerCount(srv);
+
+ return 0;
+}
+
+
+static bool
+daemonServerWorkersDone(virNetDaemonPtr dmn)
+{
+ size_t workerCount = 0;
+
+ virHashForEach(dmn->servers, daemonServerWorkerCount, &workerCount);
+
+ return workerCount == 0;
+}
+
+
void
virNetDaemonRun(virNetDaemonPtr dmn)
{
@@ -843,6 +870,9 @@ virNetDaemonRun(virNetDaemonPtr dmn)
virObjectLock(dmn);
virHashForEach(dmn->servers, daemonServerProcessClients, NULL);
+
+ if (dmn->quitRequested && daemonServerWorkersDone(dmn))
+ dmn->quit = true;
}
cleanup:
@@ -868,7 +898,7 @@ virNetDaemonQuit(virNetDaemonPtr dmn)
virObjectLock(dmn);
VIR_DEBUG("Quit requested %p", dmn);
- dmn->quit = true;
+ dmn->quitRequested = true;
virHashForEach(dmn->servers, daemonServerQuitRequested, NULL);
virObjectUnlock(dmn);
--
2.13.6