Skip to content

fix(http): route HTTP-mode sockets through close_socket on force close - #65

Open
detail-app[bot] wants to merge 1 commit into
mainfrom
detail/bug-fix/fix-http-route-http-mode-sockets-through-close-soc-d6b17d
Open

detail-app[bot] wants to merge 1 commit into
mainfrom
detail/bug-fix/fix-http-route-http-mode-sockets-through-close-soc-d6b17d

Conversation

@detail-app

@detail-app detail-app Bot commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

Detail bug report: View on Detail

Change

elide_transport_socket_close never checked whether a socket was in HTTP mode and never routed through http::close_socket. It removed the raw connection, workload, and serving entries while leaving the state.http.sockets entry behind. When no cancellable operation remained at close time — the normal state on non-io_uring backends and on io_uring with non-default capacity — nothing ever completed for that socket again, so the HTTP state became a permanent zombie: no EVENT_CLOSED was delivered, queued response parts were silently dropped, and the http.sockets entry (exchanges, retry list, pinned-body accounting) leaked until driver retirement.

The fix adds an http::is_http check at the top of elide_transport_socket_close. If the socket is in HTTP mode, it calls http::close_socket (the same teardown path the workload-sweep already uses) and extends the resulting events into state.http.overflow for delivery on the next poll. This matches the semantics consumers already observe when an operation happens to be in flight at close time — it only extends the teardown to the window where the accidental persistent-receive net is absent.

Affected layers: Rust ABI (crates/bemo/src/abi/socket.rs), integration tests (crates/bemo/tests/http.rs). No ABI symbol, layout, or version changes.

Closes #58

Validation

  • cargo build --workspace --locked — passes
  • cargo fmt --package bemo --check — passes
  • cargo clippy --package bemo --all-targets --locked -- -D warnings — passes
  • cargo test --workspace --doc --locked — passes
  • cargo test --manifest-path fuzz/Cargo.toml --lib --locked — passes (7/7 fuzz seed replays)
  • cargo nextest run -p bemo --lib --tests --locked (default/auto backend) — 387/389 pass; 2 pre-existing failures (persistent_keepalive_reuses_receive_registration_and_fixed_send_state, arm_receive_failure_leaves_socket_dormant) confirmed present on the unmodified baseline via git stash
  • ELIDE_TRANSPORT_TEST_BACKEND=epoll cargo nextest run -p bemo --lib --tests --locked --profile epoll — 389/389 pass (the backend where the bug manifested)
  • ELIDE_TRANSPORT_TEST_BACKEND=io-uring cargo nextest run -p bemo --lib --tests --locked — 387/389 pass (same 2 pre-existing failures)

Six new integration tests added to crates/bemo/tests/http.rs, all passing on default, epoll, and io_uring backends:

  • parked_http_socket_close_emits_closed_and_cleans_up — the core bug: a parked HTTP socket (body larger than BODY_WINDOW_BYTES, segments never acked) force-closed via socket_close delivers EVENT_CLOSED and drains the owner budget
  • parked_http_socket_close_fails_queued_streaming_parts — queued streaming response parts are failed with EVENT_PART_SENT error events rather than silently dropped
  • non_http_socket_close_is_unaffected — non-HTTP sockets still follow the raw close path
  • double_close_of_http_socket_returns_invalid — second close returns INVALID
  • close_http_socket_with_inflight_receive_emits_one_closed — exactly one EVENT_CLOSED (no duplicates from the cancellation completion path)
  • ack_after_parked_close_produces_no_events — acking held segments after close cannot resurrect the socket or produce new HTTP events

Platform tested: Linux (epoll and io_uring). No ABI version or layout changes; no FFM or Native Image impact.


Automatic Fixes PRs can be configured here.

@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.83%. Comparing base (26fb123) to head (c9d8872).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@             Coverage Diff              @@
##               main      #65      +/-   ##
============================================
+ Coverage     86.82%   86.83%   +0.01%     
+ Complexity      616      615       -1     
============================================
  Files            60       60              
  Lines         16979    16985       +6     
  Branches        490      490              
============================================
+ Hits          14742    14749       +7     
  Misses         1913     1913              
+ Partials        324      323       -1     
Flag Coverage Δ
jvm 57.47% <ø> (-0.04%) ⬇️
rust 93.03% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@codspeed

codspeed Bot commented Oct 17, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

⚠️ 6 benchmarks spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

✅ 117 untouched benchmarks
⏩ 65 skipped benchmarks1


Comparing detail/bug-fix/fix-http-route-http-mode-sockets-through-close-soc-d6b17d (c9d8872) with main (26fb123)

Open in CodSpeed

Footnotes

  1. 65 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

This branch has not been deployed

No deployments
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.

[Detail Bug] HTTP sockets force-closed via socket_close can leak HTTP state and never emit EVENT_CLOSED

0 participants