Skip to content

fix: enable SO_REUSEADDR in native listener for rapid restarts - #27

Merged
oboard merged 1 commit into
mainfrom
worktree-fix-reuseaddr
Aug 21, 2026
Merged

fix: enable SO_REUSEADDR in native listener for rapid restarts#27
oboard merged 1 commit into
mainfrom
worktree-fix-reuseaddr

Conversation

@oboard

@oboard oboard commented Aug 21, 2026

Copy link
Copy Markdown
Owner

What

The native Mocket listener previously constructed @http.Server(addr) without reuse_addr, so SO_REUSEADDR was disabled (the pinned moonbitlang/async@0.21.0 TcpServer defaults it to false). During rapid development restarts, a socket left in TIME_WAIT on the same 127.0.0.1:PORT can make the new process report "Address already in use" even though no process is listening.

Fix

Pass reuse_addr=true when building the native HTTP server:

let server = @http.Server(addr, reuse_addr=true) catch { ... }

This lets a fresh process immediately rebind a port a previous process just left in TIME_WAIT.

Also

  • Documented the SO_REUSEADDR behavior and the moonbitlang/async BSD/macOS side effect directly on listen_ffi: with reuse enabled, a bind to a specific address may "steal" the interface from an existing wildcard 0.0.0.0 bind, and a wildcard bind can bind to the remaining interfaces if a specific-interface bind already exists.

Verification

  • moon check is green on native, js, and wasm.
  • Ran the responder example on :4000, sent traffic (HTTP 200), killed the process, and immediately relaunched — the second server successfully rebinds the same port.

Note

The "propagate bind failures as checked errors" improvement is a separate, larger API-signature change (the public Mocket::listen/serve are Unit noraise); I scoped this PR to the primary fix.

🤖 Generated with Claude Code

Pass `reuse_addr=true` when constructing the native HTTP server so a new
process can immediately rebind a port that a previous process left in
TIME_WAIT. Without it, repeated development restarts on the same address
can fail with "Address already in use" even though no process is listening.

Document the BSD/macOS side effect noted by moonbitlang/async: with
reuse_addr enabled, a specific-address bind may steal an interface from a
wildcard bind and vice versa.

Co-Authored-By: Claude <noreply@anthropic.com>
@oboard
oboard merged commit f6ca77b into main Aug 21, 2026
1 check failed
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