-/* $OpenBSD: vmd.c,v 1.27 2016/02/05 11:40:15 reyk Exp $ */
+/* $OpenBSD: vmd.c,v 1.28 2016/07/29 16:36:51 stefan Exp $ */
/*
* Copyright (c) 2015 Reyk Floeter <reyk@openbsd.org>
memcpy(&vmr, imsg->data, sizeof(vmr));
if ((vm = vm_getbyvmid(imsg->hdr.peerid)) == NULL)
fatalx("%s: invalid vm response", __func__);
+ vm->vm_pid = vmr.vmr_pid;
vcp = &vm->vm_params;
vcp->vcp_id = vmr.vmr_id;
}
break;
case IMSG_VMDOP_TERMINATE_VM_RESPONSE:
+ case IMSG_VMDOP_TERMINATE_VM_EVENT:
IMSG_SIZE_CHECK(imsg, &vmr);
memcpy(&vmr, imsg->data, sizeof(vmr));
- proc_forward_imsg(ps, imsg, PROC_CONTROL, -1);
+ if (imsg->hdr.type == IMSG_VMDOP_TERMINATE_VM_RESPONSE)
+ proc_forward_imsg(ps, imsg, PROC_CONTROL, -1);
if (vmr.vmr_result == 0) {
/* Remove local reference */
vm = vm_getbyid(vmr.vmr_id);
return (NULL);
}
+struct vmd_vm *
+vm_getbypid(pid_t pid)
+{
+ struct vmd_vm *vm;
+
+ TAILQ_FOREACH(vm, env->vmd_vms, vm_entry) {
+ if (vm->vm_pid == pid)
+ return (vm);
+ }
+
+ return (NULL);
+}
+
void
vm_remove(struct vmd_vm *vm)
{
-/* $OpenBSD: vmd.h,v 1.21 2016/07/09 09:06:22 stefan Exp $ */
+/* $OpenBSD: vmd.h,v 1.22 2016/07/29 16:36:51 stefan Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
IMSG_VMDOP_GET_INFO_VM_DATA,
IMSG_VMDOP_GET_INFO_VM_END_DATA,
IMSG_VMDOP_LOAD,
- IMSG_VMDOP_RELOAD
+ IMSG_VMDOP_RELOAD,
+ IMSG_VMDOP_TERMINATE_VM_EVENT
};
struct vmop_result {
int vmr_result;
uint32_t vmr_id;
+ pid_t vmr_pid;
char vmr_ttyname[VM_TTYNAME_MAX];
};
struct vmd_vm {
struct vm_create_params vm_params;
+ pid_t vm_pid;
uint32_t vm_vmid;
int vm_kernel;
int vm_disks[VMM_MAX_DISKS_PER_VM];
struct vmd_vm *vm_getbyvmid(uint32_t);
struct vmd_vm *vm_getbyid(uint32_t);
struct vmd_vm *vm_getbyname(const char *);
+struct vmd_vm *vm_getbypid(pid_t);
void vm_remove(struct vmd_vm *);
char *get_string(uint8_t *, size_t);
-/* $OpenBSD: vmm.c,v 1.33 2016/07/19 09:52:34 natano Exp $ */
+/* $OpenBSD: vmm.c,v 1.34 2016/07/29 16:36:51 stefan Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/queue.h>
+#include <sys/wait.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/time.h>
struct ns8250_regs com1_regs;
io_fn_t ioports_map[MAX_PORTS];
+void vmm_sighdlr(int, short, void *);
int start_client_vmd(void);
int opentap(void);
int start_vm(struct imsg *, uint32_t *);
if (config_init(ps->ps_env) == -1)
fatal("failed to initialize configuration");
+ signal_del(&ps->ps_evsigchld);
+ signal_set(&ps->ps_evsigchld, SIGCHLD, vmm_sighdlr, ps);
+ signal_add(&ps->ps_evsigchld, NULL);
+
#if 0
/*
* pledge in the vmm process:
return (0);
}
+void
+vmm_sighdlr(int sig, short event, void *arg)
+{
+ struct privsep *ps = arg;
+ int status;
+ uint32_t vmid;
+ pid_t pid;
+ struct vmop_result vmr;
+ struct vmd_vm *vm;
+ struct vm_terminate_params vtp;
+
+ switch (sig) {
+ case SIGCHLD:
+ do {
+ pid = waitpid(-1, &status, WNOHANG);
+ if (pid <= 0)
+ continue;
+
+ if (WIFEXITED(status) || WIFSIGNALED(status)) {
+ vm = vm_getbypid(pid);
+ if (vm == NULL) {
+ /*
+ * If the VM is gone already, it
+ * got terminated via a
+ * IMSG_VMDOP_TERMINATE_VM_REQUEST.
+ */
+ continue;
+ }
+
+ vmid = vm->vm_params.vcp_id;
+ vtp.vtp_vm_id = vmid;
+ if (terminate_vm(&vtp) == 0) {
+ memset(&vmr, 0, sizeof(vmr));
+ vmr.vmr_result = 0;
+ vmr.vmr_id = vmid;
+ vm_remove(vm);
+ if (proc_compose_imsg(ps, PROC_PARENT,
+ -1, IMSG_VMDOP_TERMINATE_VM_EVENT,
+ 0, -1, &vmr, sizeof(vmr)) == -1)
+ log_warnx("could not signal "
+ "termination of VM %u to "
+ "parent", vmid);
+ } else
+ log_warnx("could not terminate VM %u",
+ vmid);
+ } else
+ fatalx("unexpected cause of SIGCHLD");
+ } while (pid > 0 || (pid == -1 && errno == EINTR));
+ break;
+ default:
+ fatalx("unexpected signal");
+ }
+}
+
/*
* vcpu_reset
*
if (ret > 0) {
/* Parent */
+ vm->vm_pid = ret;
+
for (i = 0 ; i < vcp->vcp_ndisks; i++) {
close(vm->vm_disks[i]);
vm->vm_disks[i] = -1;
pthread_t *tid;
void *exit_status;
struct vm_run_params **vrp;
- struct vm_terminate_params vtp;
if (vcp == NULL)
return (EINVAL);
if (exit_status != NULL) {
log_warnx("%s: vm %d vcpu run thread %zd exited "
"abnormally", __progname, vcp->vcp_id, i);
- /* Terminate the VM if we can */
- memset(&vtp, 0, sizeof(vtp));
- vtp.vtp_vm_id = vcp->vcp_id;
- if (terminate_vm(&vtp)) {
- log_warnx("%s: could not terminate vm %d",
- __progname, vcp->vcp_id);
- }
ret = EIO;
}
}