Skip to content

[PHP] fix: preserve orderly TCP close across bridges#755

Merged
brandonpayton merged 3 commits into
integration/kd-6nz-php-phpt-platform-fixesfrom
gascity/kd-6nz/kd-q3m-pr717-tcp-close-stack
Jul 11, 2026
Merged

[PHP] fix: preserve orderly TCP close across bridges#755
brandonpayton merged 3 commits into
integration/kd-6nz-php-phpt-platform-fixesfrom
gascity/kd-6nz/kd-q3m-pr717-tcp-close-stack

Conversation

@brandonpayton

@brandonpayton brandonpayton commented Jun 20, 2026

Copy link
Copy Markdown
Member

Why

TCP close is an orderly, simplex FIN operation: already-queued bytes must remain readable, each direction closes independently, and FIN must not be fabricated into an exact count of successful later writes. Kandelo's pipe-backed loopback sockets, Node bridge, and virtual network instead mixed orderly close with reset behavior and tied accepted bridges too closely to the process that originally accepted them. That broke ordinary stream shutdown, blocked-I/O wakeups, and forked socket ownership.

This constituent repairs that platform contract across the kernel and both host networking backends. It is stacked into the still-unmerged Batch 2 aggregate because its new host/kernel export must be included in the aggregate ABI 16→17 reconciliation before any main landing.

Source change

The two original commits introduced allowHalfOpen/orderly Node close handling, separated virtual FIN from abort, and changed pipe-backed TCP close behavior. The original implementation also invented an "exactly one write after FIN" rule and a one-second forced-destroy timer; neither accurately models TCP.

Review changes

The appended corrective commit:

  • replaces the fabricated one-write allowance with a persistent pipe-backed discard sink that lasts until the peer writer closes, while exposing whether a real reader still exists;
  • adds the additive kernel_pipe_has_readers kernel export and regenerates abi/snapshot.json;
  • consumes shutdown pipe/host references exactly once and makes SHUT_RDWR writes report EPIPE/SIGPIPE correctly;
  • preserves queued pre-FIN data and lets Node drain through allowHalfOpen, end(), and destroySoon() rather than timer-driven truncation;
  • makes direct Node pipe reads, writes, EOF, and abort issue the correct readable/writable wakeups;
  • retains partially delivered virtual-network data across backpressure and keeps the receive direction live after SHUT_WR;
  • repairs accepted-bridge and listener ownership across fork(), including final-owner cleanup and port reuse;
  • rejects enabled SO_LINGER with EOPNOTSUPP instead of silently promising unsupported close behavior;
  • documents the remaining accepted pipe-bridge reset limitation truthfully (reset is currently observed as EOF/EPIPE); and
  • adds guest-level Node, virtual-network, fork, large-payload, zero-byte-FIN, shutdown, and Sortix/browser coverage.

View

Accept into Batch 2 only. The repaired FIN/reset separation, backpressure, wakeups, and ownership model are sound based on review and focused validation. It is intentionally not independently main-ready: host/src/kernel-worker.ts now requires kernel_pipe_has_readers, while this constituent still reports ABI 16. Existing prebuilt ABI-16 kernels do not provide that export. Batch 2 must make this part of its promised ABI 16→17 reconciliation, rebuild generated artifacts, and pass the full aggregate gate before #871 can advance.

Validation

Run through scripts/dev-shell.sh on the repaired source tree unless noted:

  • cargo test -p kandelo --target aarch64-apple-darwin --lib: 1,010 passed, 0 failed.
  • cd host && npx vitest run test/virtual-network-e2e.test.ts test/tcp-backend.test.ts test/virtual-network.test.ts: 32 passed, 2 skipped.
  • cd host && npm run typecheck: passed.
  • bash build.sh: passed.
  • scripts/run-sortix-tests.sh --sequential basic sys_socket/tcp-peer-close-eof-epipe sys_socket/tcp-shutdown-half-close sys_socket/tcp-shutdown-matrix: 3/3 passed.
  • The same three Sortix socket cases passed in real headed Chromium: each returned exit code 0 with no runner error.
  • bash scripts/check-abi-version.sh: snapshot/header/TypeScript bindings are synchronized; the structural diff is the additive kernel_pipe_has_readers export. This is not a semantic ABI-clearance claim.
  • git diff --check: clean.

The exact full host run and canonical ./run.sh browser startup were attempted but reached the generated PHP artifact and failed at the known missing env.__wasm_posix_vm_interrupt_after import supplied by #757. They are recorded as failed aggregate attempts, not passes. A final browser network-lab rerun was also blocked by the currently generated GNU netcat artifact, which fails its own Node netcat tests; the real-browser Sortix close/shutdown cases above are the final browser evidence for this constituent. The complete host, libc, ABI, and browser gate remains due on #871's reconciled final head.

Stack and provenance

  • Target: integration/kd-6nz-php-phpt-platform-fixes ([PHP] Batch 2: PHPT platform and ABI fixes #871).
  • Repaired replay preserving the two unique source commits:
    • ec4b05cee fix: close bridged TCP sockets gracefully
    • 2c2d967d5 fix: model TCP close as orderly FIN
  • Append-only corrective commit: 1d697bac5 fix: preserve orderly TCP close across bridges.
  • The source branch was replaced with --force-with-lease from its reviewed old head so the repaired replay, rather than the stale stack ancestry, is what enters Batch 2.

Supersedes the old fork-headed #735.

@github-actions

Copy link
Copy Markdown

Phase B-1 matrix build status — pr-755-staging

ABI v15. 6 built, 0 failed, 6 total.

Package Arch Status Sha
kandelo-sdk wasm32 built bbcaea9f
rootfs wasm32 built 3e34a9d0
shell wasm32 built 16aa686a
lamp wasm32 built 88379fdd
node-vfs wasm32 built 7aecb2ac
wordpress wasm32 built 5810f4f5

Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.

Kandelo Agent and others added 3 commits July 10, 2026 20:55
Tie accepted connection lifetime to pipe ownership, retain inbound data across backpressure, wake blocked pipe I/O, and drain queued output before FIN.

Model final TCP receive ownership as a discard sink, reject unsupported enabled SO_LINGER, and record the additive real-reader ABI export.
@brandonpayton brandonpayton force-pushed the gascity/kd-6nz/kd-q3m-pr717-tcp-close-stack branch from 3da3a8f to 1d697ba Compare July 11, 2026 02:03
@brandonpayton brandonpayton changed the title [PHP] fix: split TCP close semantics stack [PHP] fix: preserve orderly TCP close across bridges Jul 11, 2026
@brandonpayton brandonpayton changed the base branch from integration/kd-6nz-php-phpt-tcp-epipe-sigpipe-base to integration/kd-6nz-php-phpt-platform-fixes July 11, 2026 02:05
@brandonpayton brandonpayton merged commit 9fdb5e5 into integration/kd-6nz-php-phpt-platform-fixes Jul 11, 2026
@brandonpayton brandonpayton deleted the gascity/kd-6nz/kd-q3m-pr717-tcp-close-stack branch July 11, 2026 02:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant