1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! Scratch experiment (not part of the public API): what a **child-process** event does to the
//! two things a caller might use as a target identity — the session's process *set*
//! ([`DebugEngine::session_processes`]) and the engine's *current* process
//! ([`DebugEngine::current_process_system_id`]).
//!
//! The question it settles is not whether the set changes — of course it does — but whether the
//! **selection moves with it**. If a child appearing also makes the child current, then every
//! read a caller makes afterwards is of the child rather than of the process they opened, and a
//! handle that went on certifying the original is certifying something it cannot deliver. If the
//! selection stays put, a child is a bystander and the set changing is a false alarm.
//!
//! ```text
//! cargo run --example child_process_identity
//! ```
//!
//! The engine has to be in `target/debug/examples`; see `breakpoint_probe`'s header.
//!
//! Measured on dbgeng 10.0.26100.1 (ARM64, 2026-09-25), launching `cmd.exe /c ping -n 2`:
//!
//! ```text
//! at the initial break set=[2368] current=2368
//! after .childdbg 1 set=[2368] current=2368
//! g #1 -> Break instruction exception
//! after g #1 set=[1000, 2368] current=1000 <-- the child is current
//! g #2 -> target_gone true
//! ```
//!
//! **The selection moves with the set.** The engine stops at the child's create event and makes
//! the *child* the current process, so every register read, memory read and stack walk after that
//! point is of the child rather than of the process the session was opened for — without anything
//! having been asked of the debugger. That is the answer a caller needs: a child appearing is not
//! a bystander it can ignore, because the thing its own reads resolve against has moved.
use DebugEngine;
/// A launch that spawns a child promptly: `cmd.exe` runs `ping` as a separate process.
const LAUNCH: &str = "cmd.exe /c ping -n 2 127.0.0.1";