From a42b46dd7db2cafe77010bfae55f2e4631a26844 Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Fri, 13 Nov 2020 10:56:59 +0100 Subject: [PATCH] virnetdaemon: Wait for "daemon-stop" thread to finish before quitting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the host is shutting down then we get PrepareForShutdown signal on DBus to which we react by creating a thread which runs virStateStop() and thus qemuStateStop(). But if scheduling the thread is delayed just a but it may happen that we receive SIGTERM (sent by systemd) to which we respond by quitting our event loop and cleaning up everything (including drivers). And only after that the thread gets to run only to find qemu_driver being NULL. What we can do is to delay exiting event loop and join the thread that's executing virStateStop(). If the join doesn't happen in given timeout (currently 30 seconds) then libvirtd shuts down forcefully anyways (see virNetDaemonRun()). Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1895359 Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1739564 Signed-off-by: Michal Privoznik Reviewed-by: Ján Tomko --- src/libvirt_remote.syms | 1 + src/remote/remote_daemon.c | 15 ++++++++++++--- src/rpc/virnetdaemon.c | 17 +++++++++++++++++ src/rpc/virnetdaemon.h | 3 +++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms index d398d20880..3cd84a0854 100644 --- a/src/libvirt_remote.syms +++ b/src/libvirt_remote.syms @@ -88,6 +88,7 @@ virNetDaemonQuit; virNetDaemonRemoveShutdownInhibition; virNetDaemonRun; virNetDaemonSetShutdownCallbacks; +virNetDaemonSetStateStopWorkerThread; virNetDaemonUpdateServices; diff --git a/src/remote/remote_daemon.c b/src/remote/remote_daemon.c index 7607da94be..635e1deec8 100644 --- a/src/remote/remote_daemon.c +++ b/src/remote/remote_daemon.c @@ -529,11 +529,20 @@ static void daemonStopWorker(void *opaque) /* We do this in a thread to not block the main loop */ static void daemonStop(virNetDaemonPtr dmn) { - virThread thr; + virThreadPtr thr; virObjectRef(dmn); - if (virThreadCreateFull(&thr, false, daemonStopWorker, - "daemon-stop", false, dmn) < 0) + + thr = g_new0(virThread, 1); + + if (virThreadCreateFull(thr, true, + daemonStopWorker, + "daemon-stop", false, dmn) < 0) { virObjectUnref(dmn); + g_free(thr); + return; + } + + virNetDaemonSetStateStopWorkerThread(dmn, &thr); } diff --git a/src/rpc/virnetdaemon.c b/src/rpc/virnetdaemon.c index 5f0f078fac..e337ff1fde 100644 --- a/src/rpc/virnetdaemon.c +++ b/src/rpc/virnetdaemon.c @@ -71,6 +71,7 @@ struct _virNetDaemon { virNetDaemonShutdownCallback shutdownPrepareCb; virNetDaemonShutdownCallback shutdownWaitCb; + virThreadPtr stateStopThread; int finishTimer; bool quit; bool finished; @@ -108,6 +109,7 @@ virNetDaemonDispose(void *obj) #endif /* !WIN32 */ VIR_FORCE_CLOSE(dmn->autoShutdownInhibitFd); + VIR_FREE(dmn->stateStopThread); virHashFree(dmn->servers); @@ -773,6 +775,9 @@ daemonShutdownWait(void *opaque) if (dmn->shutdownWaitCb && dmn->shutdownWaitCb() < 0) goto finish; + if (dmn->stateStopThread) + virThreadJoin(dmn->stateStopThread); + graceful = true; finish: @@ -891,6 +896,18 @@ virNetDaemonRun(virNetDaemonPtr dmn) } +void +virNetDaemonSetStateStopWorkerThread(virNetDaemonPtr dmn, + virThreadPtr *thr) +{ + virObjectLock(dmn); + + VIR_DEBUG("Setting state stop worker thread on dmn=%p to thr=%p", dmn, thr); + dmn->stateStopThread = g_steal_pointer(thr); + virObjectUnlock(dmn); +} + + void virNetDaemonQuit(virNetDaemonPtr dmn) { diff --git a/src/rpc/virnetdaemon.h b/src/rpc/virnetdaemon.h index 6ae5305e53..fcc6e1fdff 100644 --- a/src/rpc/virnetdaemon.h +++ b/src/rpc/virnetdaemon.h @@ -69,6 +69,9 @@ int virNetDaemonAddSignalHandler(virNetDaemonPtr dmn, void virNetDaemonUpdateServices(virNetDaemonPtr dmn, bool enabled); +void virNetDaemonSetStateStopWorkerThread(virNetDaemonPtr dmn, + virThreadPtr *thr); + void virNetDaemonRun(virNetDaemonPtr dmn); void virNetDaemonQuit(virNetDaemonPtr dmn);