aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Bogorodskiy <novel@FreeBSD.org>2026-08-11 16:20:31 +0000
committerRoman Bogorodskiy <novel@FreeBSD.org>2026-08-15 08:58:02 +0000
commit1f3aeb3ea5a52e16e87439160dc19c53526600c3 (patch)
tree428c39e0a4a7782595f03101185614e58532bddc
parentfa0dc4f0f96a1b77d4be7bcdbf965897cda14521 (diff)
bhyve: monitor: detect monitor exit
Currently, sending SIGTERM to the bhyve process triggers ACPI poweroff for a VM. However, when running bhyve in monitor mode (-M), there are two processes: the monitor process and the actual VM process. Sending SIGTERM to the VM process works as before -- it powers off the VM. But sending SIGTERM to the monitor process just kills the monitor process, leaving the stale VM process running. Fix that by creating a pipe between these two processes. The child process uses the pipe to detect when the monitor goes away, and exits automatically. MFC after: 2 weeks Reviewed by: markj Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D58788
-rw-r--r--usr.sbin/bhyve/bhyverun.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index c089d1fbc8fa..339cf5071906 100644
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -54,9 +54,7 @@
#include <string.h>
#include <err.h>
#include <errno.h>
-#ifdef BHYVE_SNAPSHOT
#include <fcntl.h>
-#endif
#include <libgen.h>
#include <libutil.h>
#include <unistd.h>
@@ -127,6 +125,29 @@ static struct vcpu_info {
static cpuset_t **vcpumap;
+static void
+monitor_pipe_handler(int fd __unused, enum ev_type type __unused,
+ void *param __unused)
+{
+
+ exit(BHYVE_EXIT_ERROR);
+}
+
+static void
+monitor_pipe_init(int fd)
+{
+#ifndef WITHOUT_CAPSICUM
+ cap_rights_t rights;
+
+ cap_rights_init(&rights, CAP_EVENT);
+ if (caph_rights_limit(fd, &rights) == -1)
+ err(BHYVE_EXIT_ERROR, "Unable to apply rights to monitor pipe");
+#endif
+
+ if (mevent_add(fd, EVF_READ, monitor_pipe_handler, NULL) == NULL)
+ errx(BHYVE_EXIT_ERROR, "Unable to register parent exit event");
+}
+
/*
* XXX This parser is known to have the following issues:
* 1. It accepts null key=value tokens ",," as setting "cpus" to an
@@ -922,17 +943,29 @@ main(int argc, char *argv[])
init_bootrom(ctx);
if (get_config_bool_default("monitor", false)) {
+ int monitor_pipe[2];
+ pid_t child;
+
while (1) {
- pid_t child = fork();
+ if (pipe2(monitor_pipe, O_CLOEXEC) == -1)
+ err(BHYVE_EXIT_ERROR, "pipe2");
+
+ child = fork();
if (child == -1) {
EPRINTLN("Monitor mode fork failed: %s",
strerror(errno));
exit(BHYVE_EXIT_ERROR);
}
- if (child == 0)
+ if (child == 0) {
+ close(monitor_pipe[1]);
+ monitor_pipe_init(monitor_pipe[0]);
break;
+ }
+
+ close(monitor_pipe[0]);
while ((error = waitpid(child, &status, 0)) == -1 && errno == EINTR)
;
+ close(monitor_pipe[1]);
if (error == -1) {
EPRINTLN("Monitor mode wait failed: %s",
strerror(errno));