DebugEngine::end_session and the owning engine's Drop share the live-kernel teardown path:
- Refuse execution-control commands if the engine has no debuggee.
- Remove breakpoints through the typed interfaces, failing if any removal fails.
- Execute the engine's fixed
qdcommand and require that it no longer holds a target. - Perform passive session cleanup, regardless of the preceding outcome.
The command is encapsulated inside the typed teardown, not exposed as a new text-based API.
The previous SetExecutionStatus(GO) followed by EndSession(ACTIVE_DETACH) is not equivalent
to native KD's quit path. A finite kernel event wait is unsupported, and adding an infinite
wait would let teardown park indefinitely. No additional cross-thread engine call is used.
A failed command, failed breakpoint removal, failed status query, or a command returning with
the target still present cannot produce TargetLeft::KernelRunning. If passive cleanup succeeds,
the disposition is KernelHalted: resume is unconfirmed, and recovery may be necessary. A cleanup
failure remains an error. KernelRunning describes completion of the quit path, not an independent
measurement of guest health; a target can stop again afterward.
On 2026-09-19, the previous MCP teardown reported a successful resume/detach from a disposable
29671 Microsoft hypervisor, but its guest had a black console and stopped answering WinRM.
Native KD's subsequent qd sent an acknowledged continue packet and recovered the guest without
a reboot. Both controllers used the same DbgEng 10.0.29617.1000 image. An offline native-KD trace
against an image target also showed the frontend's passive cleanup after qd.
These observations motivate this implementation; they do not validate it against a live hypervisor. A later diagnostic stalled during initial KDNET synchronization, before reaching any detach experiment. Its explicit-target native-KD recovery attempt crashed, and passive reconnection did not establish a session. The owner subsequently recovered the guest. Repeated ordinary MCP attach/detach then reproduced a frozen guest despite an acknowledged continue; additional native recovery stops had to be released. This candidate is still not validated for that workflow.
Later comparisons changed the attach timing instead of teardown: connecting without the persistent
initial-break option, requesting one break after synchronization, and calling this same typed
teardown passed three independent guest-health checks across three runs. A further automatic
announcement-trigger comparison passed four runs (two local prototypes and two runs of the
retained example). The attach timing probe preserves the implementation,
callback measurements, and limitations. The explicitly experimental
attach_kernel_announcement_begin now offers that trigger as an opt-in typed attach path.
It does not change the ordinary attach default or establish cross-version safety.
The new local tests cover the no-debuggee guard, rejection of a target that remains present, breakpoint removal, and quit/detach leaving a disposable attached user-mode process alive. The default tests and doctests pass. Neither these tests nor Miri proves kernel transport behavior.
Before treating this path as validated, test NT and hypervisor endpoints separately, including explicit teardown and owning-engine drop, and check console/management responsiveness and uptime after each detach. Keep only one controller on an endpoint and have native KD recovery available. Do not reset a target merely because an attach times out.
Microsoft documents the deferred nature of SetExecutionStatus. Its qd reference lists user-mode support only; the hypervisor recovery above is an observation on a specific build, not a documented cross-version guarantee.