Skip to content

Host: Reuse saved GOT indices during fork replay - #1308

Open
brandonpayton wants to merge 1 commit into
mainfrom
fix/fork-replay-got-indices
Open

Host: Reuse saved GOT indices during fork replay#1308
brandonpayton wants to merge 1 commit into
mainfrom
fix/fork-replay-got-indices

Conversation

@brandonpayton

Copy link
Copy Markdown
Member

Why

A forked process can restore dynamic libraries before the parent's function
table has been reconstructed. The loader then searched that incomplete table
for GOT.func imports and could append duplicate functions at new indices.

PHP-FPM exposed the result in the WordPress/MariaDB browser image: the child
reached wpk_fork_module_state_finish_restore with table indices that no
longer matched its saved module state and trapped with unreachable.

What changed

  • Read loader-owned mutable GOT.func values from the existing fork
    module-state snapshots during replay.
  • Initialize replay globals from those exact indices without searching or
    appending duplicate functions.
  • Reconstruct a saved pre-export table gap before publishing a fresh side
    export, then let the normal sparse table restore replace the table graph.
  • Reject missing, wrong-width, or conflicting saved values and verify that
    replayed exports publish at the saved slots.
  • Regenerate package cache identities affected by the shared host sources.
  • Document the reconstruction order and add focused regression coverage.

The implementation is shared by Node.js and browser process workers. It does
not change the ABI 43 wire format, so no ABI bump or guest artifact rebuild is
required.

Validation

  • bash scripts/dev-shell.sh bash -lc 'cd host && npx vitest run test/dylink.test.ts test/fork-imported-globals.test.ts test/fork-dlopen-replay-e2e.test.ts'
    (91 tests passed, including all four real dlopen/fork end-to-end cases)
  • bash scripts/dev-shell.sh bash build.sh
  • program-index-check and program-index-context-check
  • bash scripts/dev-shell.sh bash scripts/check-abi-version.sh
  • git diff --check origin/main..HEAD

Broader-suite notes

The repository CI wrapper rejected the current
packages/registry/ruby/test/posix-spawn.test.ts inventory before starting
Vitest. A direct all-host run was also attempted but was not used as passing
evidence because unrelated tests failed. That run exposed the relevant C++
exception/TLS replay case; it is now part of the focused passing group above.

The complete browser WordPress/MariaDB reproduction was not rerun because no
corrected full service VFS artifact was produced after the local package build
was stopped.

A fork child re-instantiates dynamic libraries before restoring the
parent function table. Resolving GOT.func imports through that incomplete
table could append duplicate entries, so module-state restoration later
trapped on indices that no longer matched the parent.

Recover each loader-owned mutable GOT function value from the existing
fork module-state snapshot. Reconstruct any saved pre-export table gap,
reject missing or conflicting values, and verify that replayed exports
publish at the saved table slots.

This is an ABI 43 host reconstruction correction. It does not change the
fork snapshot wire format or require rebuilt guest artifacts. Regenerate
the package program index because the affected host sources participate
in package cache identities.

Source-commit: 1833bec04161038e76a0d2ca39990ea1c15ad29a
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