diff options
| author | Roman Bogorodskiy <novel@FreeBSD.org> | 2026-08-11 16:20:31 +0000 |
|---|---|---|
| committer | Roman Bogorodskiy <novel@FreeBSD.org> | 2026-08-15 08:58:02 +0000 |
| commit | 1f3aeb3ea5a52e16e87439160dc19c53526600c3 (patch) | |
| tree | 428c39e0a4a7782595f03101185614e58532bddc | |
| parent | fa0dc4f0f96a1b77d4be7bcdbf965897cda14521 (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.c | 41 |
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)); |
