ReviewOS

home-lang/home

HTTP proxy POST forwarding recursively drains microtasks

#628
Closed chris opened this 11 days ago ·
11 days ago

Scope

Port the Bun/Node HTTP lifecycle semantics needed by these unchanged copied corpus tests:

  • test/js/node/test/parallel/test-http-request-proxy-post.mjs
  • test/js/node/test/parallel/test-http-request-proxy-post-server-failure.mjs

The shared ESM import lowering landed in b49ba22d0, and Node common.mustCall plus referenced-handle lifecycle enforcement landed in 2edc96ed2. Both files now parse and begin executing in the reduced parity adapter, but nested POST forwarding does not complete.

Current evidence

Use the copied reducer paths, not the source Bun checkout:

zig-out/bin/home-debug test "$PWD/packages/runtime/test/bun-corpus/js/node/test/parallel/test-http-request-proxy-post.mjs"
zig-out/bin/home-debug test "$PWD/packages/runtime/test/bun-corpus/js/node/test/parallel/test-http-request-proxy-post-server-failure.mjs"
  • The server-failure reproduction entered recursive draining and reached about 3.55 GB RSS in 36 seconds before termination.
  • The successful POST path also exceeded a 20-second isolated reducer timeout after lifecycle bookkeeping was enabled.
  • Sampling showed repeated JavaScriptCore VM::drainMicrotasks frames with a deep JavaScript callback chain around URL/domain/HTTP callbacks.
  • A general experiment that stopped server request chunk delivery after serverRequest.destroyed did not resolve the loop and was not retained.
  • Neighboring unchanged reducer tests complete cleanly, so this is distinct from import syntax or generic callback bookkeeping:
    • test-http-proxy-request-connection-refused.mjs
    • test-http-proxy-request-max-sockets.mjs
    • test-http-proxy-request-socket-keep-alive.mjs
    • test-http-proxy-request-invalid-url.mjs

Acceptance criteria

  • Forward the POST body through the proxy exactly once and deliver the target response to the client.
  • Preserve a target reset through the proxy as ECONNRESET / socket hang up, allowing the proxy to produce its 500 response.
  • Both runProxiedPOST calls settle with the upstream-observed exit/result contracts.
  • Both servers and all request/response/socket resources close without recursive microtask growth or leaked event-loop ownership.
  • The unchanged upstream assertions, payload, topology, and workload pass; do not weaken fixtures, deadlines, or assertions.

Tracked from #66.

11 days ago

Validated after rebasing the import-lowering commit onto current main and rebuilding the debug runtime from source.

The unchanged test now completes consistently with the required behavior:

  • target reset becomes ECONNRESET: socket hang up
  • proxy returns status 500 with the expected response body
  • child closes with code 0 and signal null
  • 10 consecutive clean-binary runs completed in about 0.11–0.14 seconds each
  • both neighboring proxy tests remain green

The temporary diagnostic instrumentation was fully removed before the clean rebuild; the worktree is clean and there is no test-specific runtime branch. The only intervening upstream range was 147f89011..76e209ad2 in kernel codegen, so I cannot honestly attribute the earlier runaway to a dedicated HTTP source change. The accepted behavior is nevertheless reproducibly present on current main with b49ba22d0, so this focused issue is complete. If the runaway reappears under the next unfiltered corpus run, it should be reopened with that exact artifact and process context.

11 days ago

Reopening after correcting the validation path. The earlier green runs used the absolute ~/Code/bun source path, which intentionally routes through Home’s full VM. The 1,449-test parity artifact uses the copied packages/runtime/test/bun-corpus path and the reduced adapter.

Correct reducer reproduction:

zig-out/bin/home-debug test /Users/chris/Code/Home/lang-bun-port/packages/runtime/test/bun-corpus/js/node/test/parallel/test-http-request-proxy-post-server-failure.mjs

On that path the process again entered the recursive drain, reached 3,554,720 KB RSS in 36 seconds, and was terminated. The acceptance criteria remain unchanged. No diagnostic or test-specific changes were retained.

11 days ago

Resolved by 0eeca8a4e (fix(test): prevent recursive proxy forwarding). Environment proxy configuration is now consulted only when an Agent is actually selected, so the proxy helpers upstream request with agent: false bypasses the parent proxy instead of recursively dispatching into itself. Both unchanged POST cases pass together in 0.2 seconds with zero failures and zero unsupported, including body forwarding and target-reset-to-500 propagation.

Sign in to comment on this issue.