Commit 9da7163
2026.9.4.3 —— run 报告程序自己的退出码,且没有构建进程比 mcpp 活得更久 (#555)
* docs(plan): 生态批次之后剩下的四个缺口与各自的方案
Gap 4 is analysed first because the plan for it depends on the analysis. The
signature — 99.9% of one core, zero children, zero system time, on a graph whose
outputs all exist — excludes both branches of ninja's build loop that leave user
space, which narrows it to an edge that finishes WITHOUT running a command. This
graph has exactly one: the phony fed by the two `restat` staging edges, whose
command is regularly skipped while succeeding.
That the shape causes the loop remains inference. Three attempts at a stack all
failed, and the third is informative: making gdb ninja's parent, which is legal
under yama level 1, stops the spin happening at all.
Two findings from the same investigation are fully established and independent:
mcpp does not kill the ninja it spawned (one orphan outlived the removal of its
whole sandbox), and `xim:ninja@1.12.1` names two different binaries.
The other three gaps get proposals. Only `mcpp run`'s exit status needs a
decision before work starts — it is a compatibility change to a published
contract, and the note recommends rather than concludes.
* 2026.9.4.3 —— run 报告程序自己的退出码,且没有构建进程比 mcpp 活得更久
两条缺陷,来自 2026-09-04 那份生态批次留下的四个缺口(§3 与 §5.1 of
`.agents/docs/2026-09-04-four-gaps-after-the-ecosystem-batch.md`)。
## `mcpp run` REPORTS THE PROGRAM'S OWN EXIT STATUS
Both spawn sites ended in `return rc == 0 ? 0 : 1`, so that 2 could mean "could
not start" as distinct from "ran and failed". The distinction was worth keeping;
the price was not. Measured: a program whose `main` returns 3 made `mcpp run`
exit 1, and a bare-metal image qemu reported as 3 arrived as 1 as well. A
command that cannot report a status cannot be used in a script, which is most of
what `mcpp run` is for — and this project's claim is that running on a device is
like running hosted.
Three bands, and only the first belongs to the program:
0-124 the program's own status, passed through
125-127 the spawn was attempted and refused (127 not found,
126 found but not executable, 125 anything else)
2 mcpp refused before attempting anything
THE MIDDLE BAND IS THE SHELL'S, NOT THIS PROJECT'S. `env`, `timeout` and `nice`
already answer 126/127 with these meanings, so a reader who meets one does not
have to look it up, and "could not start" lands there by meaning rather than by
allocation.
A program may itself exit 125-127 and mcpp does not disambiguate by number: what
separates them is that a launcher failure always writes a reason to stderr and a
program's own status never does.
COMPATIBILITY IS THE REASON 2 STAYS WHERE IT IS. mcpp's own refusals — no binary
target, no runner declared, a runner not on PATH — keep exit 2, which is what
every other mcpp command uses. Only "the spawn was refused" moves, and in that
case the program never ran. `mcpp test` is unchanged at 0/1: it aggregates many
programs and has no single status to pass through.
## NO BUILD PROCESS SURVIVES THE mcpp THAT STARTED IT
Measured in the ecosystem sandbox: every `timeout`-terminated `mcpp run` left an
orphaned ninja spinning at 100% of a core, and one outlived the removal of the
entire sandbox it belonged to — its working directory read `(deleted)`. Any CI
that wraps mcpp in `timeout` leaked a busy core per timeout.
The child now gets its own process group (a job object on Windows), and mcpp
SIGKILLs that group on SIGINT/SIGTERM/SIGHUP. THE GROUP RATHER THAN THE PID,
because the child starts children of its own: killing ninja alone would leave
its compilers behind.
SIGKILL RATHER THAN SIGTERM, AND THAT IS NOT AN ESCALATION FOR ITS OWN SAKE.
ninja records a signal in a flag and acts on it where it waits for a subprocess;
a ninja with no command running never reaches that check, so a polite signal is
recorded and never obeyed. That is precisely the state the orphans were in.
THE GUARD BECOMES A REGISTRY. A spanning `[hooks]` command is guarded for the
length of the build and the build's own ninja for the length of its run —
concurrently. With one slot the second registration disarmed the first, so
killing mcpp mid-build would have taken ninja down and left the hook running.
BOTH LAUNCHERS, WHICH THE TEST CAUGHT. `run_exec` was fixed first and the A/B
still showed an orphan: a full build spawns ninja through `capture_exec`, and
fixing one of the two left the defect in the common path.
## `MCPP_NINJA_DEBUG`
Appends `-d <topics>` to both ninja launches. The ninja spin that this batch
could not root-cause is unreachable by debugger — `ptrace_scope=1`,
`perf_event_paranoid=4`, and making gdb its parent stops the spin happening —
so ninja's own `-d explain` is the only instrument left.
## Tests
`339` covers all three exit bands including the boundary a band split gets
wrong: a program exiting 127 itself, which must produce no mcpp error line.
`340` signals mcpp's pid ALONE, because `timeout` and Ctrl-C both signal the
process group and reached ninja even before the fix — a test built on `timeout`
passes either way. It also requires that ninja was seen alive first: an earlier
draft killed mcpp after the build had finished and passed without measuring
anything, and a second draft used 200 parallel units that a 32-core host
finished inside the window. `--jobs 1` makes the window deterministic by
construction. Verified to FAIL against the released 2026.9.4.2, naming the
orphan and its deleted working directory.
`330`'s unrunnable-artifact assertion moves from 2 to 126; the three assertions
around it that cover mcpp's own pre-flight refusals are deliberately unchanged.
---------
Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>1 parent 1c2603c commit 9da7163
15 files changed
Lines changed: 992 additions & 53 deletions
File tree
- .agents/docs
- docs
- zh
- modules
- platform/src
- unix
- windows
- versioning/src
- src
- build
- tests/e2e
Lines changed: 359 additions & 0 deletions
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 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 | + | |
6 | 52 | | |
7 | 53 | | |
8 | 54 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
179 | 179 | | |
180 | 180 | | |
181 | 181 | | |
182 | | - | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
183 | 214 | | |
184 | 215 | | |
185 | 216 | | |
| |||
194 | 225 | | |
195 | 226 | | |
196 | 227 | | |
197 | | - | |
| 228 | + | |
198 | 229 | | |
199 | 230 | | |
200 | 231 | | |
| |||
316 | 347 | | |
317 | 348 | | |
318 | 349 | | |
319 | | - | |
| 350 | + | |
320 | 351 | | |
321 | 352 | | |
322 | 353 | | |
323 | 354 | | |
324 | 355 | | |
325 | | - | |
| 356 | + | |
326 | 357 | | |
327 | 358 | | |
328 | 359 | | |
| |||
367 | 398 | | |
368 | 399 | | |
369 | 400 | | |
370 | | - | |
| 401 | + | |
371 | 402 | | |
372 | 403 | | |
373 | 404 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
153 | 153 | | |
154 | 154 | | |
155 | 155 | | |
156 | | - | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
157 | 182 | | |
158 | 183 | | |
159 | 184 | | |
| |||
166 | 191 | | |
167 | 192 | | |
168 | 193 | | |
169 | | - | |
| 194 | + | |
170 | 195 | | |
171 | 196 | | |
172 | 197 | | |
| |||
280 | 305 | | |
281 | 306 | | |
282 | 307 | | |
283 | | - | |
| 308 | + | |
284 | 309 | | |
285 | 310 | | |
286 | 311 | | |
287 | 312 | | |
288 | | - | |
| 313 | + | |
289 | 314 | | |
290 | 315 | | |
291 | 316 | | |
| |||
324 | 349 | | |
325 | 350 | | |
326 | 351 | | |
327 | | - | |
| 352 | + | |
328 | 353 | | |
329 | 354 | | |
330 | 355 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
| 3 | + | |
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
189 | 189 | | |
190 | 190 | | |
191 | 191 | | |
192 | | - | |
| 192 | + | |
193 | 193 | | |
194 | 194 | | |
195 | 195 | | |
| |||
596 | 596 | | |
597 | 597 | | |
598 | 598 | | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
599 | 621 | | |
600 | | - | |
601 | | - | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
602 | 625 | | |
603 | 626 | | |
604 | 627 | | |
605 | 628 | | |
606 | 629 | | |
607 | 630 | | |
608 | 631 | | |
| 632 | + | |
609 | 633 | | |
610 | 634 | | |
| 635 | + | |
611 | 636 | | |
612 | 637 | | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
613 | 650 | | |
614 | 651 | | |
615 | | - | |
616 | | - | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
617 | 668 | | |
618 | 669 | | |
619 | 670 | | |
| |||
652 | 703 | | |
653 | 704 | | |
654 | 705 | | |
| 706 | + | |
| 707 | + | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
| 714 | + | |
| 715 | + | |
655 | 716 | | |
656 | | - | |
| 717 | + | |
| 718 | + | |
657 | 719 | | |
658 | 720 | | |
| 721 | + | |
659 | 722 | | |
660 | 723 | | |
661 | 724 | | |
| |||
671 | 734 | | |
672 | 735 | | |
673 | 736 | | |
| 737 | + | |
674 | 738 | | |
675 | 739 | | |
676 | 740 | | |
| |||
889 | 953 | | |
890 | 954 | | |
891 | 955 | | |
892 | | - | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
893 | 960 | | |
894 | | - | |
| 961 | + | |
895 | 962 | | |
896 | | - | |
| 963 | + | |
897 | 964 | | |
898 | 965 | | |
899 | 966 | | |
| |||
0 commit comments