Skip to content

fix(ws): route WebSocketServer.close to js_ws_server_close and box cl… - #8

Merged
andilv merged 1 commit into
mainfrom
fix/ws-server-close-and-handle-boxing
Aug 10, 2026
Merged

andilv merged 1 commit into
mainfrom
fix/ws-server-close-and-handle-boxing

Conversation

@andilv

@andilv andilv commented Aug 10, 2026

Copy link
Copy Markdown
Owner

…ient handles

wss.close() resolved to the generic client-only js_ws_close entry — a server handle is never in WS_CONNECTIONS, so it silently no-op'd and WS_ACTIVE_SERVERS kept the event loop alive forever. Add a class-filtered NET_EVENTS row dispatching WebSocketServer.close to js_ws_server_close.

Also NaN-box numeric ws ids with POINTER_TAG in js_ws_process_pending (perry-ext-ws + perry-stdlib) so handles handed to user TS unbox back to the real id via the unbox_to_i64 receiver contract instead of 0, matching the new WebSocket ctor path.

Summary

Changes

Related issue

Test plan

  • cargo build --release clean
  • cargo test --workspace --exclude perry-ui-ios --exclude perry-ui-tvos --exclude perry-ui-watchos --exclude perry-ui-gtk4 --exclude perry-ui-android --exclude perry-ui-windows passes
  • (if user-facing) Added or updated a test under test-files/ or a #[test] in the affected crate
  • (if CLI / stdlib / runtime API changed) Updated docs/src/
  • (if touching a platform UI backend) Built -p perry-ui-<backend> locally on that platform

Screenshots / output

Checklist

  • I have NOT bumped the workspace version or edited CLAUDE.md / CHANGELOG.md (maintainer handles these at merge)
  • My commits follow the loose feat: / fix: / docs: / chore: prefix convention used in the log
  • I've read CONTRIBUTING.md and agree to the Code of Conduct

…ient handles

`wss.close()` resolved to the generic client-only `js_ws_close` entry — a
server handle is never in WS_CONNECTIONS, so it silently no-op'd and
WS_ACTIVE_SERVERS kept the event loop alive forever. Add a class-filtered
NET_EVENTS row dispatching WebSocketServer.close to js_ws_server_close.

Also NaN-box numeric ws ids with POINTER_TAG in js_ws_process_pending
(perry-ext-ws + perry-stdlib) so handles handed to user TS unbox back to
the real id via the unbox_to_i64 receiver contract instead of 0, matching
the `new WebSocket` ctor path.
@andilv
andilv merged commit 4b83af2 into main Aug 10, 2026
31 of 49 checks passed
andilv added a commit that referenced this pull request Sep 1, 2026
7 upstream commits since a03be72, incl. PerryTS#9343 (split ws dispatch rows out
of net_events.rs into ws_events.rs) and PerryTS#9335 (WebSocketServer.clients Set).

net_events.rs conflicted (fork's ws-server-close row vs upstream's split):
- net_events.rs: take upstream's version (ws section moved to ws_events.rs).
  This also resolves the fork's file-size lint failure (2003 -> 1863 lines).
- ws_events.rs: carry the fork's WebSocketServer.close -> js_ws_server_close
  class-filtered row over from net_events.rs so the server-close fix (PR #8)
  survives the split.

perry-ext-ws/src/lib.rs and perry-stdlib/src/ws.rs auto-merged (fork's handle
boxing + upstream's clients Set tracking both retained; compile-checked).
andilv pushed a commit that referenced this pull request Sep 22, 2026
…ic TLS (PerryTS#10399)

glibc carves a thread's static TLS block out of the same mapping as its
stack. Once module state is per-thread, OpenCode's binary carries 5.79 MB
of PT_TLS (up from 263 KB), so against tokio's 2 MB default the blocking
threads had almost no usable stack left and SIGSEGV'd deep inside
reqwest's connector on first use:

    Thread 2 "tokio-rt-worker" received signal SIGSEGV
    #0 reqwest::connect::ConnectorService::call
    #8 perry_ext_fetch::do_fetch
    #9 perry_ffi::async_runtime::spawn_blocking_with_reactor::invoke

The main thread, whose TLS is allocated separately, was unaffected —
which is why only commands that touch the network died while --version
and --help passed.

Proven by A/B on the built binary: `opencode models` dumps core at the
default stack and prints the model list under RUST_MIN_STACK=16MB. The
full CLI ladder goes 4/10 -> 8/10, which matches the pre-change binary
measured with the same ladder, so this is not a regression.

Reserves 32 MB for the blocking pool and for worker_threads workers,
overridable with PERRY_THREAD_STACK_SIZE. A stack is reserved address
space committed lazily, so the reservation costs no RSS.

Claude-Session: https://claude.ai/code/session_017utYgB6CH497RthE5Y3fTe
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