dinit: preserve SIGCHLD reaping across Wasm SjLj#911
Conversation
Wasm SjLj represents siglongjmp as an exception transfer. Dasynq's noexcept pselect boundary intercepts that transfer in a nearer termination region before pull_events can resume its local sigsetjmp landing pad, so Dinit aborts while reaping a completed scripted service. Remove only that incompatible portability boundary, compile Dinit with the Wasm exception model it requires, and advance the package revision for the changed artifacts. Add raw and fork-instrumented negative controls, a positive SIGCHLD/reap fixture, real Dinit supervision coverage, and a main-compatible dinitctl exception regression. The raw module remains a test-only packed fixture, never a publishable program artifact. This changes Dinit package bytes but does not change the Kandelo ABI.
|
Independent devil review: ACCEPT exact head The reviewer covered the full pre-squash range, reran the canonical program build, 7/7 focused tests, host typecheck, ABI consistency, syntax/diff checks, raw/instrumented structure, CI workspace packing, PID-aware teardown, and a tree-identical synthetic merge. The accepted two-commit candidate was then squashed without changing its reviewed tree. No code finding remains. The operational overlap with #907 is real and is documented in the PR body; this PR must not be merged ahead of the locked batch under an assumption of a conflict-free mechanical merge. |
Phase B-1 matrix build status —
|
| Package | Arch | Status | Sha |
|---|---|---|---|
| dinit | wasm32 | built | d4cfb9b0 |
| lamp | wasm32 | built | 2f0f1075 |
| mariadb-test | wasm32 | built | 0c3317cf |
| mariadb-vfs | wasm32 | built | 82f551c4 |
| mariadb-vfs | wasm64 | built | 46f39a72 |
| wordpress | wasm32 | built | 039a8dba |
Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.
|
CI follow-up at The test now has an explicit 30-second outer deadline covering startup, the existing 10-second behavioral guard, and cleanup. No Dinit/runtime behavior or artifact input changed. The exact focused command passed 6/6 tests, with the real scripted-service case completing in 834 ms:
The same old run also failed |
|
Hosted rerun classification at exact head
This run confirms the Dinit timeout correction made its intended behavioral deadline reachable. It does not introduce a new Dinit failure; the red Vitest status is the already isolated teardown-readiness race. |
|
Merged PR #907 supersedes this work through the strengthened Dinit lifecycle fixes now on main at |
|
Post-#907 cleanup audit: recording the still-current branch head |
|
The useful test and documentation follow-up is now #925, with the underlying LLVM limitation still tracked in #918. #907 already landed the Dinit production and package fix. #925 deliberately keeps only generic raw and fork-instrumented controls, the positive SIGCHLD fixture, Node and Chromium coverage including wasm64, and SDK documentation; it does not replay Dinit patches or package revisions. The old remote head was c6737de. |
Purpose
Keep Dinit's SIGCHLD event path from aborting when Dasynq resumes its
pselectloop withsiglongjmpunder WebAssembly SjLj.Root cause
Wasm SjLj represents
siglongjmpwith a dedicated exception transfer. Dasynq'spselect_events::pull_events(bool) noexceptcontains the correspondingsigsetjmplanding, but Clang also emits a nearer catch-all termination region for thenoexceptboundary. The signal handler's jump reaches that termination region first, callsstd::terminate, and exits with status 134 before Dinit can reap the completed scripted service.Raw clang-linked and fork-instrumented controls fail identically. This is a C++/Wasm SjLj portability boundary, not a fork-instrumentation failure and not a Kandelo signal or process-state shortcut.
What changes
noexceptonly from the affected pselect polling boundary.-fwasm-exceptions, using the declared Nix host compiler for native generators.dinitctlexception test.local-binaries/test-fixtures, outside the publishable program artifact namespace.noexcept/SjLj ordering boundary in the SDK guide.Validation
All build and test commands ran through
scripts/dev-shell.sh.scripts/build-programs.sh: passed.noexceptcontrols: both entered the handler, exited 134 withlibc++abi: terminating, and did not reach the landing.noexceptfixture: resumed the same SjLj tag and exited 0.[ OK ] childobserved, then the known Dinit PID was terminated and awaited before host teardown.dinitctl: expected exit 1 and missing-socket stderr, with no Wasm exception or libc++ termination.xtask build-deps checkand Dinit manifest parse: passed.origin/main2c083e143618e4974a637b649e6221c64f0dd936: clean and tree-identical.No dedicated browser UI suite was run for this standalone package PR. The same revision-5 Dinit bytes are part of the ABI 39 batch's Node/browser integration path.
ABI and package impact
This changes Dinit package bytes and therefore advances its package revision. It does not change the Kandelo kernel/host ABI, syscall semantics, channel layout, memory layout, or fork instrumentation contract;
ABI_VERSIONand the ABI snapshot are unchanged.ABI 39 batch relationship
#907 head
0f464442db59397fab7098ae154d7e9640cc345calready carries the same semantic Dinit repair in commits085371b1and0f464442, plus an ABI-39-only host-diagnostics assertion. This dedicated PR is the focused review vehicle with stronger raw/instrumented negative proof.Do not mechanically merge this PR ahead of #907 while assuming the locked batch remains conflict-free: the two branches intentionally overlap in the Dinit build, patch, and test files. The batch should retain its ABI-39-only diagnostic delta and treat this reviewed tree as the provenance for the shared repair.