Use process exit as termination confirmation.

This commit is contained in:
Michael Lipp 2025-03-13 10:25:32 +01:00
parent 72e1b8a580
commit f493a2c582
4 changed files with 38 additions and 23 deletions

View file

@ -21,8 +21,8 @@
# Defaults for namespace (VM domain)
handlers=java.util.logging.ConsoleHandler
#org.jgrapes.level=FINE
#org.jgrapes.core.handlerTracking.level=FINER
org.jgrapes.level=FINE
org.jgrapes.core.handlerTracking.level=FINER
org.jdrupes.vmoperator.runner.qemu.level=FINEST

View file

@ -242,7 +242,7 @@ public abstract class QemuConnector extends Component {
*/
@Handler
public void onClosed(Closed<?> event, SocketIOChannel channel) {
channel.associated(this, getClass()).ifPresent(qm -> {
channel.associated(this, getClass()).ifPresent(qc -> {
qemuChannel = null;
});
}

View file

@ -42,6 +42,7 @@ import org.jgrapes.core.Components.Timer;
import org.jgrapes.core.annotation.Handler;
import org.jgrapes.core.events.Stop;
import org.jgrapes.io.events.Closed;
import org.jgrapes.io.events.ProcessExited;
import org.jgrapes.net.SocketIOChannel;
import org.jgrapes.util.events.ConfigurationUpdate;
@ -136,24 +137,12 @@ public class QemuMonitor extends QemuConnector {
* @param event the event
*/
@Handler
@SuppressWarnings({ "PMD.AvoidSynchronizedStatement",
"PMD.AvoidDuplicateLiterals" })
public void onClosed(Closed<?> event, SocketIOChannel channel) {
channel.associated(this, getClass()).ifPresent(qm -> {
super.onClosed(event, channel);
logger.finer(() -> "QMP socket closed.");
monitorReady = false;
channel.associated(this, getClass()).ifPresent(qm -> {
synchronized (this) {
if (powerdownTimer != null) {
powerdownTimer.cancel();
}
if (suspendedStop != null) {
suspendedStop.resumeHandling();
suspendedStop = null;
}
}
});
logger.finer(() -> "QMP socket closed.");
}
/**
@ -163,7 +152,8 @@ public class QemuMonitor extends QemuConnector {
* @throws IOException
*/
@Handler
@SuppressWarnings("PMD.AvoidSynchronizedStatement")
@SuppressWarnings({ "PMD.AvoidSynchronizedStatement",
"PMD.AvoidDuplicateLiterals" })
public void onMonitorCommand(MonitorCommand event) throws IOException {
// Check prerequisites
if (!monitorReady && !(event.command() instanceof QmpCapabilities)) {
@ -228,7 +218,9 @@ public class QemuMonitor extends QemuConnector {
}
/**
* On powerdown event.
* When the powerdown event is confirmed, wait for termination
* or timeout. Termination is detected by the qemu process exiting
* (see {@link #onProcessExited(ProcessExited)}).
*
* @param event the event
*/
@ -258,6 +250,29 @@ public class QemuMonitor extends QemuConnector {
}
}
/**
* On process exited.
*
* @param event the event
*/
@Handler
@SuppressWarnings("PMD.AvoidSynchronizedStatement")
public void onProcessExited(ProcessExited event) {
if (!event.startedBy().associated(CommandDefinition.class)
.map(cd -> Runner.QEMU.equals(cd.name())).orElse(false)) {
return;
}
synchronized (this) {
if (powerdownTimer != null) {
powerdownTimer.cancel();
}
if (suspendedStop != null) {
suspendedStop.resumeHandling();
suspendedStop = null;
}
}
}
/**
* On configure qemu.
*

View file

@ -195,9 +195,9 @@ import org.jgrapes.util.events.WatchFile;
"PMD.CouplingBetweenObjects", "PMD.TooManyFields" })
public class Runner extends Component {
private static final String QEMU = "qemu";
private static final String SWTPM = "swtpm";
private static final String CLOUD_INIT_IMG = "cloudInitImg";
public static final String QEMU = "qemu";
public static final String SWTPM = "swtpm";
public static final String CLOUD_INIT_IMG = "cloudInitImg";
private static final String TEMPLATE_DIR
= "/opt/" + APP_NAME.replace("-", "") + "/templates";
private static final String DEFAULT_TEMPLATE