]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
virnetdaemon: Wait for "daemon-stop" thread to finish before quitting
authorMichal Privoznik <mprivozn@redhat.com>
Fri, 13 Nov 2020 09:56:59 +0000 (10:56 +0100)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 24 Nov 2020 16:52:54 +0000 (17:52 +0100)
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 <mprivozn@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/libvirt_remote.syms
src/remote/remote_daemon.c
src/rpc/virnetdaemon.c
src/rpc/virnetdaemon.h

index d398d208809840e367ec9213507c402271f3c928..3cd84a08545c0af8be555dbb4c3550e57694beae 100644 (file)
@@ -88,6 +88,7 @@ virNetDaemonQuit;
 virNetDaemonRemoveShutdownInhibition;
 virNetDaemonRun;
 virNetDaemonSetShutdownCallbacks;
+virNetDaemonSetStateStopWorkerThread;
 virNetDaemonUpdateServices;
 
 
index 7607da94be90905ba75fed4235e3a9c8dfdb8b86..635e1deec884b49410ea16748dd9e816b46e07de 100644 (file)
@@ -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);
 }
 
 
index 5f0f078fac453df9899e3f120dd24cc047af3898..e337ff1fdeef6d700e3d94275c1ec04fe1bb164b 100644 (file)
@@ -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)
 {
index 6ae5305e53891603d8e8586658ea911c68d3e07f..fcc6e1fdffeb1e37e60367ee44e4af10492d7ec7 100644 (file)
@@ -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);