Virtualization.framework VM execution ownership and crash reclamation on Intel macOS Monterey

Subject: Virtualization.framework VM execution ownership and crash reclamation on Intel macOS Monterey

Hello,

I’m investigating the lifecycle guarantees of Virtualization.framework on Intel macOS Monterey 12.7.x.

The specific scenario is a VZVirtualMachine running a Linux guest. I need to understand the ownership and reclamation behavior when the process holding the VZVirtualMachine is abruptly terminated without calling stop() or performing normal cleanup.

The key questions are:

  1. For a specific VZVirtualMachine on Intel macOS Monterey, which userspace task/process actually owns the Hypervisor VM and the vCPU threads backing guest execution?

    Is Hypervisor execution owned directly by the calling process, or by a separate process such as:

    com.apple.Virtualization.VirtualMachine

    or another Virtualization.framework backend?

  2. If the process holding the VZVirtualMachine is terminated with SIGKILL or crashes without executing cleanup code, is the underlying guest execution context necessarily destroyed?

    More specifically:

    • Can guest vCPU execution continue after the client process has died?
    • If a separate backend process owns the VM, is that backend guaranteed to terminate or destroy the VM when the client dies?
    • Does this behavior apply to Intel macOS Monterey 12.7.x, or only to newer macOS releases?
  3. Is there a supported diagnostic on Monterey that can map one specific VZVirtualMachine instance to the task/process that actually owns its Hypervisor VM/vCPU execution?

    For example, would a diagnostic showing Hypervisor execution frames such as hv_vcpu_run in a process, combined with a reliable process-exit notification, be sufficient to establish that ownership relationship?

  4. If the Virtualization backend can survive the client process, what supported VM-specific recovery or termination mechanism is available to another process?

The security property I need to establish is intentionally narrow:

If the userspace owner of a VM is abruptly destroyed, guest computation must not be able to continue indefinitely as an independent execution domain.

Persistent disk files or other inert VM artifacts are not the concern; the question is specifically about live guest/vCPU execution and its ownership lifecycle.

I’m looking for the supported architectural contract or diagnostic approach, not undocumented implementation details.

Target environment:

  • macOS Monterey 12.7.x
  • Intel x86_64
  • Virtualization.framework
  • Hypervisor.framework
  • Hardware virtualization available
  • No private APIs or privileged/kernel extensions

Thank you.

Answered by DTS Engineer in 907320022

Hmmm, that wasn’t the answer I was expecting, but it’s good to know.

The general rule here is that the app that invokes Virtualization framework is responsible for any VMs it creates. If the app terminates unexpectedly, the system should clean up its resources, and that includes killing any VMs that it might’ve left running.

This is the expected behaviour on all versions of macOS. I’m not aware of any bugs that prevent this, but such bugs are always a possibility.

The exact mechanics of this are considered implementation details. That includes the identities of any processes involved and the way that they were launched. For example, I ran a quick test on my Mac (running 26.6.1) and it seems that some of the processes spun up by Virtualization are closely associated with the specific Virtualization client but others are per user. For example, com.apple.Virtualization.VirtualMachine is the former group but com.apple.Virtualization.EventTap is in the latter. However, these processes and their relationships are most definitely implementation details, not something you can rely on.

That means that you can’t draw too many conclusions from the lifetime of these processes. For example, when I force quit the VM app I found that some processes terminated and some didn’t. This makes sense when you think about how the pre-user processes interact with macOS’s on-demand architecture.

Note If you’re curious about that architecture, it’s something I discuss in XPC and App-to-App Communication.

Is there a supported diagnostic [to] map one specific VZVirtualMachine instance to the task/process that actually owns its Hypervisor VM/vCPU execution?

I’ll note that this request is reasonable in that it’s about diagnostics, and diagnostics are one of the cases where it’s useful to factor in implementation details.

However, there isn’t a good technique for this. It’s likely that you’d be able to infer these relationships using either the system log or launchctl procinfo, but there’s nothing that’ll do this directly.

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

The way you’ve phrased your question suggests that you only care about macOS 12, which is a bit weird. Most folks with questions like this are concerned about macOS 12 and later. So:

  • Is it that macOS 12 is your minimum deployment target, and thus you’re looking for answers for macOS 12 and later?
  • Or are you solely interested in the behaviour of macOS 12?

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for checking. For this specific investigation, I am primarily interested in macOS Monterey 12.7.x on Intel x86_64, rather than treating macOS 12 merely as a minimum deployment target. The reason is that I need to establish a security/lifecycle property for that exact host environment: if the userspace process responsible for a running VZVirtualMachine is abruptly destroyed, I need to know whether the live guest/vCPU execution is necessarily reclaimed and cannot continue independently. Behavior on newer macOS releases would certainly be useful context, especially if the ownership model changed over time, but a guarantee that applies only to newer releases would not establish the property I need for Monterey. So, ideally, I’m looking for the answer specifically for Intel macOS Monterey 12.7.x. If the behavior is the same from Monterey onward, that would of course also be very useful to know.

Hmmm, that wasn’t the answer I was expecting, but it’s good to know.

The general rule here is that the app that invokes Virtualization framework is responsible for any VMs it creates. If the app terminates unexpectedly, the system should clean up its resources, and that includes killing any VMs that it might’ve left running.

This is the expected behaviour on all versions of macOS. I’m not aware of any bugs that prevent this, but such bugs are always a possibility.

The exact mechanics of this are considered implementation details. That includes the identities of any processes involved and the way that they were launched. For example, I ran a quick test on my Mac (running 26.6.1) and it seems that some of the processes spun up by Virtualization are closely associated with the specific Virtualization client but others are per user. For example, com.apple.Virtualization.VirtualMachine is the former group but com.apple.Virtualization.EventTap is in the latter. However, these processes and their relationships are most definitely implementation details, not something you can rely on.

That means that you can’t draw too many conclusions from the lifetime of these processes. For example, when I force quit the VM app I found that some processes terminated and some didn’t. This makes sense when you think about how the pre-user processes interact with macOS’s on-demand architecture.

Note If you’re curious about that architecture, it’s something I discuss in XPC and App-to-App Communication.

Is there a supported diagnostic [to] map one specific VZVirtualMachine instance to the task/process that actually owns its Hypervisor VM/vCPU execution?

I’ll note that this request is reasonable in that it’s about diagnostics, and diagnostics are one of the cases where it’s useful to factor in implementation details.

However, there isn’t a good technique for this. It’s likely that you’d be able to infer these relationships using either the system log or launchctl procinfo, but there’s nothing that’ll do this directly.

Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you, Quinn. This is very helpful and clears up the distinction I was struggling with between the supported Virtualization.framework lifecycle contract and the implementation details of the helper processes. In particular, your clarification that an unexpectedly terminated Virtualization.framework client should have its VMs cleaned up by the system, and that this is the expected behavior across macOS versions, answers the main question I was trying to resolve. I also understand now that process names, process relationships, and process lifetime are implementation details and therefore aren’t appropriate as an ownership or VM-liveness contract. I have one final architecture-level question, if you don’t mind: Is it reasonable for an application to rely on this client-lifetime → VM-cleanup behavior as part of the supported Virtualization.framework lifecycle contract when designing a bounded VM execution host? In other words, assuming the application still implements its own normal stop/timeout/cleanup paths, can it reasonably treat unexpected client termination as a failure case where macOS is expected to terminate the VM rather than allowing that VM’s execution to continue independently? I’m not asking for guarantees about private helper processes or implementation details — only whether that high-level lifecycle behavior is an appropriate supported assumption for application architecture. Thanks again for taking the time to clarify this.

Virtualization.framework VM execution ownership and crash reclamation on Intel macOS Monterey
 
 
Q