virNetDaemonLifecycleCallback shutdownPrepareCb;
virNetDaemonLifecycleCallback shutdownWaitCb;
virThread *stateStopThread;
+ int stopTimer;
int quitTimer;
virNetDaemonQuitPhase quit;
bool graceful;
static virClass *virNetDaemonClass;
+/*
+ * When running state stop operation which can be slow...
+ *
+ * How frequently we tell systemd to extend our stop time,
+ * and how much we ask for each time. The latter should
+ * exceed the former with a decent tolerance for high load
+ * scenarios
+ */
+#define VIR_NET_DAEMON_STOP_EXTEND_INTERVAL_MSEC (5 * 1000)
+#define VIR_NET_DAEMON_STOP_EXTRA_TIME_SEC 10
+
+/*
+ * When running daemon shutdown synchronization which
+ * ought to be moderately fast
+ */
+#define VIR_NET_DAEMON_SHUTDOWN_TIMEOUT_SEC 30
+#define VIR_NET_DAEMON_SHUTDOWN_TIMEOUT_MSEC (VIR_NET_DAEMON_SHUTDOWN_TIMEOUT_SEC * 1000)
+
+
static int
daemonServerClose(void *payload,
const char *key G_GNUC_UNUSED,
if (virEventRegisterDefaultImpl() < 0)
goto error;
+ dmn->stopTimer = -1;
dmn->autoShutdownTimerID = -1;
#ifndef WIN32
}
}
+static void
+virNetDaemonStopTimer(int timerid G_GNUC_UNUSED,
+ void *opaque)
+{
+ virNetDaemon *dmn = opaque;
+ VIR_LOCK_GUARD lock = virObjectLockGuard(dmn);
+
+ if (dmn->quit != VIR_NET_DAEMON_QUIT_STOPPING)
+ return;
+
+ VIR_DEBUG("Extending stop timeout %u",
+ VIR_NET_DAEMON_STOP_EXTRA_TIME_SEC);
+
+ virSystemdNotifyExtendTimeout(VIR_NET_DAEMON_STOP_EXTRA_TIME_SEC);
+}
+
+
static void
virNetDaemonQuitTimer(int timerid G_GNUC_UNUSED,
void *opaque)
if (dmn->quit == VIR_NET_DAEMON_QUIT_REQUESTED) {
VIR_DEBUG("Process quit request");
+ virSystemdNotifyStopping();
virHashForEach(dmn->servers, daemonServerClose, NULL);
if (dmn->stateStopThread) {
VIR_DEBUG("State stop thread running");
dmn->quit = VIR_NET_DAEMON_QUIT_STOPPING;
+ virSystemdNotifyExtendTimeout(VIR_NET_DAEMON_STOP_EXTRA_TIME_SEC);
+ if ((dmn->stopTimer = virEventAddTimeout(VIR_NET_DAEMON_STOP_EXTEND_INTERVAL_MSEC,
+ virNetDaemonStopTimer,
+ dmn, NULL)) < 0) {
+ VIR_WARN("Failed to register stop timer");
+ /* hope for the best */
+ }
} else {
VIR_DEBUG("Ready to shutdown");
dmn->quit = VIR_NET_DAEMON_QUIT_READY;
if (dmn->shutdownPrepareCb && dmn->shutdownPrepareCb() < 0)
break;
- if ((dmn->quitTimer = virEventAddTimeout(30 * 1000,
+ virSystemdNotifyExtendTimeout(VIR_NET_DAEMON_SHUTDOWN_TIMEOUT_SEC);
+ if ((dmn->quitTimer = virEventAddTimeout(VIR_NET_DAEMON_SHUTDOWN_TIMEOUT_MSEC,
virNetDaemonQuitTimer,
dmn, NULL)) < 0) {
VIR_WARN("Failed to register finish timer.");
dmn->quit = VIR_NET_DAEMON_QUIT_READY;
}
g_clear_pointer(&dmn->stateStopThread, g_free);
+ if (dmn->stopTimer != -1) {
+ virEventRemoveTimeout(dmn->stopTimer);
+ dmn->stopTimer = -1;
+ }
}
VIR_DEBUG("End stop dmn=%p", dmn);