[PHP] fix: preserve process-shared state across fork and exec#756
Merged
brandonpayton merged 19 commits intoJul 11, 2026
Conversation
Phase B-1 matrix build status —
|
| Package | Arch | Status | Sha |
|---|---|---|---|
| libcurl | wasm32 | built | a6f6534d |
| libcxx | wasm32 | built | 0d3c1977 |
| libcxx | wasm64 | built | 3117bdac |
| libiconv | wasm32 | built | 1be46463 |
| libiconv | wasm64 | built | 82d9fdf3 |
| libpng | wasm32 | built | 697eac68 |
| libxml2 | wasm32 | built | 41fada20 |
| libxml2 | wasm64 | built | b3752126 |
| openssl | wasm32 | built | 96fbd5a6 |
| openssl | wasm64 | built | b53b8ff0 |
| sqlite | wasm32 | built | 10a86a4f |
| sqlite | wasm64 | built | e74c37db |
| zlib | wasm32 | built | 1b3d5c6f |
| zlib | wasm64 | built | 8470f519 |
| bc | wasm32 | built | 645e81c1 |
| bzip2 | wasm32 | built | 85ec619a |
| coreutils | wasm32 | built | d0c76ab8 |
| curl | wasm32 | built | 3dfec8e7 |
| dash | wasm32 | built | 04d2f6b8 |
| diffutils | wasm32 | built | c804830a |
| dinit | wasm32 | built | e646ca69 |
| fbdoom | wasm32 | built | 935a71b0 |
| file | wasm32 | built | b9e73f9f |
| findutils | wasm32 | built | aeeb6ecc |
| gawk | wasm32 | built | 9c6d61e9 |
| git | wasm32 | built | ad9f9d06 |
| grep | wasm32 | built | c6aa7ff9 |
| gzip | wasm32 | built | 6c492249 |
| kandelo-sdk | wasm32 | built | fa69e4fc |
| kernel | wasm32 | failed | — |
| less | wasm32 | built | 87aa211f |
| lsof | wasm32 | built | c88ab5c9 |
| m4 | wasm32 | built | 5847a852 |
| make | wasm32 | failed | — |
| mariadb | wasm32 | built | d5d40cc7 |
| mariadb | wasm64 | built | 8c75bf16 |
| modeset | wasm32 | built | e5967428 |
| msmtpd | wasm32 | built | cff25a9b |
| nano | wasm32 | built | d850deac |
| ncurses | wasm32 | built | 9a77777f |
| netcat | wasm32 | built | e8e76c42 |
| nginx | wasm32 | built | 3742a74e |
| php | wasm32 | built | 6c215a1d |
| posix-utils-lite | wasm32 | built | 3ab77df9 |
| sed | wasm32 | built | ef08c754 |
| spidermonkey | wasm32 | built | d1b3e35c |
| tar | wasm32 | built | 7ac89a61 |
| tcl | wasm32 | built | 1e64df4d |
| unzip | wasm32 | built | 3f650bbb |
| userspace | wasm32 | built | 4dcfe62b |
| vim | wasm32 | built | 9c5d375e |
| wget | wasm32 | built | 2b0aaa25 |
| xz | wasm32 | built | dba87aba |
| zip | wasm32 | built | f1c66da0 |
| zstd | wasm32 | built | 4381b467 |
| bash | wasm32 | built | 479f8133 |
| mariadb-test | wasm32 | built | 95e7de82 |
| mariadb-vfs | wasm32 | built | 9cca8b82 |
| mariadb-vfs | wasm64 | built | 97bcd722 |
| nethack | wasm32 | built | 6198392e |
| node | wasm32 | built | cfe2bfc0 |
| spidermonkey-node | wasm32 | built | eee81883 |
| vim-browser-bundle | wasm32 | built | cb17bc3a |
| nethack-browser-bundle | wasm32 | built | 0d6d8f1e |
| rootfs | wasm32 | failed | — |
| shell | wasm32 | failed | — |
| node-vfs | wasm32 | built | f8a54c30 |
Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.
This was referenced Jul 10, 2026
Merge anonymous MAP_SHARED and SysV writes against per-mapping snapshots at syscall boundaries, inherit their host backing across fork, and publish/detach them exactly once across exec, exit, and crash paths. Keep Node, browser, and the main-thread test host in parity, including signal-style cleanup when a fork-child worker fails. File-backed mapping identity is handled separately.
Move eventfd, timerfd, signalfd, memfd, and procfs snapshot state into refcounted kernel-global backing tables so inherited open file descriptions keep one coherent identity across fork and spawn. Balance backing ownership through close, rollback, process removal, CLOFORK filtering, and retained legacy exec state while rejecting unreconstructable fresh-instance handles instead of aliasing stale slots. Use the shared backing as the authoritative memfd/procfs cursor for reads, seeks, fdinfo, and SEEK_CUR locks. Keep host clock callbacks outside the backing lock and preserve existing fresh-kernel fork/exec behavior for ordinary reconstructable descriptors.
Emit versioned fork-instrument role claims, preserve an ABI-16 legacy fallback, and make ABI 17 activate mandatory side-entry and dlopen-main validation. Drive side-module unwind and rewind through an immutable main trampoline while persisting the active side buffer and exact table layout for child replay. Reject statically visible nested side-module fork paths, roll failed loads back transactionally, retain first-definition symbol bindings, and document the remaining opaque-callback and pthread boundaries. Exercise repeated main-to-side fork and wait cycles with a real instrumented fixture.
Route host-originated shared signals to the exact eligible thread and rebind asynchronous channel completions before dequeueing. Consumed or ignored signals no longer shorten sleeps, and a kernel trap cannot trigger a false wake. Treat process exit as terminal across specialized host-side syscall dispatches, including mmap writeback and synthetic memory operations. Guard address-space teardown against re-entrant signal cleanup so crash, exec-handoff, and clean-exit paths notify parents exactly once without resuming dead guest code.
brandonpayton
force-pushed
the
gascity/kd-6nz/kd-e0l-pr717-fork-process-shm-split
branch
from
July 11, 2026 09:23
9a7ec18 to
953d8af
Compare
brandonpayton
changed the base branch from
integration/kd-6nz-php-phpt-socket-network-base
to
integration/kd-6nz-php-phpt-platform-fixes
July 11, 2026 09:23
brandonpayton
deleted the
gascity/kd-6nz/kd-e0l-pr717-fork-process-shm-split
branch
July 11, 2026 09:24
brandonpayton
added a commit
that referenced
this pull request
Jul 11, 2026
Merge the address-sorted guest mapping and host reservation streams without materializing a combined list. Normalize fork-restored mappings once at their ingestion boundary so the ordering invariant is explicit. Reference-equivalence tests cover interleaving, equal starts, overlap, exact fits, exhaustion, and systematic relative orderings. The copied munmap regression from the original PR remains owned by #756. This is an unmeasured internal refactor. It makes no throughput or PHP/PHPT coverage claim and changes no intended host or ABI contract.
brandonpayton
added a commit
that referenced
this pull request
Jul 11, 2026
Merge the address-sorted guest mapping and host reservation streams without materializing a combined list. Normalize fork-restored mappings once at their ingestion boundary so the ordering invariant is explicit. Reference-equivalence tests cover interleaving, equal starts, overlap, exact fits, exhaustion, and systematic relative orderings. The copied munmap regression from the original PR remains owned by #756. This is an unmeasured internal refactor. It makes no throughput or PHP/PHPT coverage claim and changes no intended host or ABI contract.
brandonpayton
added a commit
that referenced
this pull request
Jul 12, 2026
Merge the address-sorted guest mapping and host reservation streams without materializing a combined list. Normalize fork-restored mappings once at their ingestion boundary so the ordering invariant is explicit. Reference-equivalence tests cover interleaving, equal starts, overlap, exact fits, exhaustion, and systematic relative orderings. The copied munmap regression from the original PR remains owned by #756. This is an unmeasured internal refactor. It makes no throughput or PHP/PHPT coverage claim and changes no intended host or ABI contract.
13 tasks
brandonpayton
added a commit
that referenced
this pull request
Jul 13, 2026
Wait and signal results, mmap placement and ownership, exec cleanup, descriptor/socket/shared-memory inheritance, fork metadata, epoll, sleep, and signal-death behavior all change existing process contracts. Advance ABI 25 to 26 and regenerate ABI evidence atomically. Require kernel_get_process_exit_signal so a missing kernel contract fails loudly. Retain file-backed MAP_SHARED handles across unlink, and drain last-owned host descriptors during forced process removal so the epoch is self-contained beneath its integration tests. Source-PR: #756 Folded-Repair: 01907159db3a092d76cc695b948f58bf0b52d0d7 Folded-Reconstruction: required-export model coverage b1eb8f24d and the shared-memory XFAIL retirement c8cd117a6.
brandonpayton
added a commit
that referenced
this pull request
Jul 13, 2026
Merge the address-sorted guest mapping and host reservation streams without materializing a combined list. Normalize fork-restored mappings once at their ingestion boundary so the ordering invariant is explicit. Reference-equivalence tests cover interleaving, equal starts, overlap, exact fits, exhaustion, and systematic relative orderings. The copied munmap regression from the original PR remains owned by #756. This is an unmeasured internal refactor. It makes no throughput or PHP/PHPT coverage claim and changes no intended host or ABI contract.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
Preserve authoritative process, descriptor, and shared-memory state across
fork()andexec()so PHP-FPM and other multi-process POSIX software use thenormal Kandelo platform path.
This replaces the stale split branch's eight unique commits on an altered
socket integration base with nineteen reviewed, append-only repair commits on
the exact Batch 2 aggregate tip (
e45019127). It intentionally does not replaythe altered socket base wholesale.
Reviewed result
zombie/wait authority through host worker lifecycle transitions.
fallible exec preparation before destructive state changes.
OFDs and kernel-backed objects while closing CLOEXEC descriptors and resetting
image-specific state.
MAP_SHAREDbackings, and refcounted eventfd/timerfd/signalfd/memfd/procfs state across
fork/spawn/exec at the correct ownership boundary.
transactional table/archive replay and rollback.
boundaries. Host-originated shared signals select the exact eligible TID;
ignored signals do not shorten sleeps, and no specialized host dispatch
resumes guest code after signal death.
WebAssembly/host boundaries.
the exit-signal query optional for compatible ABI-16 hosts.
Review changes
The review rebuilt the constituent rather than force-fitting its stale socket
ancestry. The nineteen commits repair:
identity, dirty/version merging, direct-I/O coherence, partial unmaps,
MAP_FIXEDpreflight, and exact lifecycle publication;pthread sleep correctness;
re-entrant address-space teardown guards.
Independent final audits found no remaining constituent blocker.
Review view
Accept into quarantined Batch 2 via rebase merge. Do not land this PR directly
to
main. The repaired constituent is coherent on the current #871 tip andkeeps its changes linearly revertible, but Batch 2 still needs the single atomic
ABI 16→17 reconciliation for the two divergent ABI-16 epochs and rebuilt PHP /
opcache artifacts.
Known boundaries remain explicit:
MAP_SHAREDcoherence occurs at mediated syscall/lifecycle boundaries,not as immediate shared physical memory;
ENOTSUP;SIGBUS;mandatory with the aggregate ABI-17 bump.
Validation
All claimed commands ran through
scripts/dev-shell.sh.cargo test -p kandelo --target aarch64-apple-darwin --lib4987bae1d; no Rust/ABI/generated file changed afterwardcargo test -p fork-instrument --target aarch64-apple-darwincargo test -p wasm-posix-shared --target aarch64-apple-darwindump_abitestsbash scripts/check-abi-version.shat953d8afb9vse45019127cd host && npx vitest runat953d8afb9cd host && npm run buildnpx tsx examples/run-example.ts examples/mmap_shared_anonymous_fork.wasmPASSFinal nine-round microbenchmarks used identical benchmark artifacts on the
candidate and exact
e45019127base:953d8afb9The Node medians are close. Chromium uses coarse buckets and its candidate
hello rounds ranged from 80.98 to 171.31 ms, so these data are not presented as
a performance-neutrality claim.
Per the locked Batch 2 policy, this constituent did not run the full
ready-to-merge libc/POSIX/PHP/PHPT/application gate, manual
./run.sh browserverification, or the full PHP browser PHPT suite. Those run once on the exact
ABI-17 aggregate. The isolated PHP image is not final-runnable here because
the harness interrupt import is supplied by #757 and final package artifacts
must be rebuilt for ABI 17.