diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/QemuMonitor.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/QemuMonitor.java index 21c3a0f..75310f8 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/QemuMonitor.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/QemuMonitor.java @@ -139,8 +139,9 @@ public class QemuMonitor extends QemuConnector { @SuppressWarnings({ "PMD.AvoidSynchronizedStatement", "PMD.AvoidDuplicateLiterals" }) public void onClosed(Closed event, SocketIOChannel channel) { - logger.finer(() -> "Closing QMP socket."); super.onClosed(event, channel); + logger.finer(() -> "QMP socket closed."); + monitorReady = false; channel.associated(this, getClass()).ifPresent(qm -> { synchronized (this) { if (powerdownTimer != null) { @@ -199,28 +200,31 @@ public class QemuMonitor extends QemuConnector { @Handler(priority = 100) @SuppressWarnings("PMD.AvoidSynchronizedStatement") public void onStop(Stop event) { - if (qemuChannel() != null) { - // We have a connection to Qemu, attempt ACPI shutdown. - event.suspendHandling(); - suspendedStop = event; - - // Attempt powerdown command. If not confirmed, assume - // "hanging" qemu process. - powerdownTimer = Components.schedule(t -> { - // Powerdown not confirmed - logger.fine(() -> "QMP powerdown command has not effect."); - synchronized (this) { - powerdownTimer = null; - if (suspendedStop != null) { - suspendedStop.resumeHandling(); - suspendedStop = null; - } - } - }, Duration.ofSeconds(1)); - logger.fine(() -> "Attempting QMP powerdown."); - powerdownStartedAt = Instant.now(); - fire(new MonitorCommand(new QmpPowerdown())); + if (!monitorReady) { + logger.fine(() -> "No QMP connection," + + " cannot send powerdown command"); + return; } + // We have a connection to Qemu, attempt ACPI shutdown. + event.suspendHandling(); + suspendedStop = event; + + // Attempt powerdown command. If not confirmed, assume + // "hanging" qemu process. + powerdownTimer = Components.schedule(t -> { + // Powerdown not confirmed + logger.fine(() -> "QMP powerdown command not confirmed"); + synchronized (this) { + powerdownTimer = null; + if (suspendedStop != null) { + suspendedStop.resumeHandling(); + suspendedStop = null; + } + } + }, Duration.ofSeconds(1)); + logger.fine(() -> "Attempting QMP powerdown."); + powerdownStartedAt = Instant.now(); + fire(new MonitorCommand(new QmpPowerdown())); } /** @@ -238,7 +242,9 @@ public class QemuMonitor extends QemuConnector { } // (Re-)schedule timer as fallback - logger.fine(() -> "QMP powerdown confirmed, waiting..."); + var waitUntil = powerdownStartedAt.plusSeconds(powerdownTimeout); + logger.fine(() -> "QMP powerdown confirmed, waiting for" + + " termination until " + waitUntil); powerdownTimer = Components.schedule(t -> { logger.fine(() -> "Powerdown timeout reached."); synchronized (this) { @@ -247,7 +253,7 @@ public class QemuMonitor extends QemuConnector { suspendedStop = null; } } - }, powerdownStartedAt.plusSeconds(powerdownTimeout)); + }, waitUntil); powerdownConfirmed = true; } }