Skip to content

feat(runtime): push external socket events host-to-guest#199

Merged
NathanFlurry merged 1 commit into
mainfrom
stack/feat-runtime-push-external-socket-events-host-to-guest-nlmypryw
Jul 2, 2026
Merged

feat(runtime): push external socket events host-to-guest#199
NathanFlurry merged 1 commit into
mainfrom
stack/feat-runtime-push-external-socket-events-host-to-guest-nlmypryw

Conversation

@NathanFlurry

Copy link
Copy Markdown
Member

Guest sockets to external hosts hung: the sidecar reader thread pushed data
into the per-socket event queue, but nothing woke the guest's read pump —
same-isolate wakes only cover loopback peers, so externally-driven sockets
had no wake source at all. Additionally the bridge's chunked-transfer decoder
treated the terminal '0 CRLF CRLF' chunk of keep-alive responses as
incomplete, so even delivered responses never completed.

  • Reader threads now push a compact net_socket stream event (cross-thread,
    never inline in RPC servicing) through the session's stream-callback
    channel; the guest bridge wakes the target socket's read pump off it.
    Push attempts/sent/missing/errors are counted in the net trace metrics.
  • Fixed terminal-chunk detection for keep-alive chunked responses.
  • New deterministic matrix ops net/http_external_get and net/tcp_external_echo
    (host-side listener started by the harness; loopback-exempt port wiring in
    the bench VM) — guest p50 ~1.0ms / ~0.8ms, event-driven rather than
    timer-paced.
  • Regression test: guest http.get reaches a host-side listener.

Remaining for #178: accept-readiness push for guest servers with external
clients (accepted-socket data is pushed; accept wakeups can still be
timer-paced), and external UDP (unsupported in the kernel-backed bridge).

Guest sockets to external hosts hung: the sidecar reader thread pushed data
into the per-socket event queue, but nothing woke the guest's read pump —
same-isolate wakes only cover loopback peers, so externally-driven sockets
had no wake source at all. Additionally the bridge's chunked-transfer decoder
treated the terminal '0 CRLF CRLF' chunk of keep-alive responses as
incomplete, so even delivered responses never completed.

- Reader threads now push a compact net_socket stream event (cross-thread,
  never inline in RPC servicing) through the session's stream-callback
  channel; the guest bridge wakes the target socket's read pump off it.
  Push attempts/sent/missing/errors are counted in the net trace metrics.
- Fixed terminal-chunk detection for keep-alive chunked responses.
- New deterministic matrix ops net/http_external_get and net/tcp_external_echo
  (host-side listener started by the harness; loopback-exempt port wiring in
  the bench VM) — guest p50 ~1.0ms / ~0.8ms, event-driven rather than
  timer-paced.
- Regression test: guest http.get reaches a host-side listener.

Remaining for #178: accept-readiness push for guest servers with external
clients (accepted-socket data is pushed; accept wakeups can still be
timer-paced), and external UDP (unsupported in the kernel-backed bridge).
@NathanFlurry

Copy link
Copy Markdown
Member Author

Stack for rivet-dev/secure-exec

Get stack: forklift get 199
Push local edits: forklift submit
Merge when ready: forklift merge 199

@railway-app
railway-app Bot temporarily deployed to secure-exec / secure-exec-pr-199 July 2, 2026 10:30 Destroyed
@NathanFlurry
NathanFlurry merged commit 3d74816 into main Jul 2, 2026
0 of 2 checks passed
@NathanFlurry
NathanFlurry deleted the stack/feat-runtime-push-external-socket-events-host-to-guest-nlmypryw branch July 2, 2026 10:30
@railway-app
railway-app Bot temporarily deployed to secure-exec / preview July 2, 2026 10:30 Inactive
@railway-app
railway-app Bot temporarily deployed to secure-exec / production July 2, 2026 10:30 Inactive
NathanFlurry added a commit that referenced this pull request Jul 2, 2026
Loopback sockets now get the same event push external sockets earned in PR
#199: the kernel socket table fires edge-triggered readiness callbacks
(empty->nonempty on recv buffers, datagram queues, and listener pending
queues; emitted outside the state lock), the sidecar routes them into
net_socket stream events (data/accept/dgram) keyed by kernel socket id, the
unix reader thread pushes like the TCP one, and the guest gained wake
latches so a wake landing while a pump is active re-pumps instead of
no-oping. Three guest cadence taxes found en route: the per-chunk
yieldBridgeMacrotask (first event-woken chunk now delivers immediately),
and reply-writes issued inside data handlers being microtask-coalesced
(handler-originated writes flush immediately). Loopback peer-wait backoff
capped at 1ms.

Release rows (vs pre-change): tcp_tiny_writes 4.55->3.0ms, udp_echo_big
1.25->0.67, unix_echo_small 5.74->3.5, unix_echo_big 7.38->5-7,
tcp_echo_small 4.02->3.2-4.8, tcp_concurrent 5.82->3.4-5. KNOWN RESIDUAL:
rows are bimodal run-to-run — a wake/pump race remains (event consumed
mid-pump -> EAGAIN -> 10ms park with no re-fire since the edge already
triggered); documented in the backlog for the next pass. http_loopback_get
carries ~+0.3ms from event overhead (0.89->1.16-1.9). Gate green; kernel
edge-trigger unit tests + isolated service regressions for TCP wake/churn,
unix echo, dgram.
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