Fix dgram UDP socket creation bugs on macOS#28084
Conversation
Three bugs in `bsd_create_udp_socket()`: 1. `bsd_set_reuseport()` was restricted to Linux only (`#if defined(__linux__)`), causing `reusePort: true` in `node:dgram` to fail on macOS with a generic error even though macOS natively supports SO_REUSEPORT. Changed to `#if defined(SO_REUSEPORT) && !defined(_WIN32)`. 2. When `bsd_set_reuse()` failed, the socket fd was leaked (not closed) and errno was not propagated to the caller, resulting in a generic "Failed to bind socket" error with no diagnostic information. 3. Errno checks for IPv4 socket option fallbacks used hardcoded value 92 (Linux ENOPROTOOPT) instead of the `ENOPROTOOPT` macro. On macOS where ENOPROTOOPT is 42, the fallback to IP_PKTINFO and IP_RECVTOS was never attempted on IPv4 sockets. Also adds regression tests for dgram implicit bind-on-send behavior (issue #28083) covering: basic send without bind, listening event, multiple queued sends, short-form send, and bidirectional k-rpc pattern. Closes #28083
|
Updated 10:04 PM PT - Mar 13th, 2026
❌ @claude, your commit 86b3ac1 has some failures in 🧪 To try this PR locally: bunx bun-pr 28084That installs a local version of the PR into your bun-28084 --bun |
|
✅ Verification complete — PR #28084 (head: All gates pass. CI green (all test platforms pass; only |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughEnabled SO_REUSEPORT when available (excluding Windows), propagate reuse-setting failures during UDP socket creation, improved IPv6→IPv4 socket-option fallback checks using ENOPROTOOPT/EINVAL, added a Win32-to-errno mapping for WSAEOPNOTSUPP, and added regression tests for implicit UDP bind/send behavior. Changes
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📝 Coding Plan
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@test/regression/issue/28083.test.ts`:
- Around line 48-79: Replace the hardcoded destination port 41234 with a
dynamically assigned port by creating a receiver socket bound to port 0 and
using its assigned port for the send; specifically, before calling
socket.send(...) create a receiver via dgram.createSocket("udp4"), call
receiver.bind(0), read the assigned port from receiver.address().port, then use
that port in the socket.send call and close the receiver when done (keep the
existing variables like socket, listeningFired, and the send callback intact).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0afd9f5e-af25-4868-8fb4-e84eed347b7a
📒 Files selected for processing (2)
packages/bun-usockets/src/bsd.ctest/regression/issue/28083.test.ts
Use a target socket bound to port 0 to get a random port, matching project guidelines for no hardcoded ports.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@test/regression/issue/28083.test.ts`:
- Around line 48-71: The socket.send callback currently ignores its err
parameter which can mask failures; inside the target.bind callback's
socket.send((err) => { ... }) handler check if err is truthy and if so write the
error or a failure marker to stdout/stderr and call process.exit(1) (or throw)
to fail the test immediately, otherwise continue with the existing
process.nextTick that writes String(listeningFired) and closes socket/target;
update the handler around socket.send to bail on err so the test doesn't produce
false-positive passes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 958152fd-833c-4f67-8e59-2904057743d5
📒 Files selected for processing (1)
test/regression/issue/28083.test.ts
Without this mapping, SystemErrno.init(10045) returns null on Windows when SO_REUSEPORT fails with WSAEOPNOTSUPP, causing an unwrap panic in udp_socket.zig.
Tests that two UDP sockets with reusePort: true can bind to the same port. This exercises the SO_REUSEPORT fix on macOS where the option was previously gated behind #if defined(__linux__).
robobun
left a comment
There was a problem hiding this comment.
Verification Report — 86b3ac1 (push 4)
Gate 1: CI ✅
Build #39529 — all test steps pass across all platforms (darwin-aarch64, darwin-x64, linux-x64, linux-aarch64, linux-musl, alpine, debian, ubuntu, windows-2019, windows-aarch64, ASAN). Only failure: upload-benchmark.mjs (infra benchmark upload script, not a test). 1 pending: windows-11-aarch64-test-bun.
Gate 2: Classification
Bug fix — test proof required.
Gate 3: Test proof ⚠️ (platform-limited)
- New test:
test/regression/issue/28083.test.ts(6 tests covering reusePort, implicit bind, listening event, multiple sends, short-form send, bidirectional k-rpc pattern) - Baked binary (main): All 6 tests pass on Linux — expected, since the bugs are macOS-specific (errno 92 vs 42 for ENOPROTOOPT, SO_REUSEPORT was already enabled on Linux)
- Darwin CI: darwin-aarch64 build+test passed — this is the platform where the fix matters
- Windows CI: windows-2019 and windows-aarch64 passed — confirms the WSAEOPNOTSUPP→ENOTSUP errno mapping fix works
Gate 4: Diff ✅
No TODOs/FIXMEs in added lines. Three C-layer fixes all match the described root causes:
SO_REUSEPORTguard:#if defined(__linux__)→#if defined(SO_REUSEPORT) && !defined(_WIN32)✓- fd leak + errno propagation on
bsd_set_reuse()failure ✓ - Hardcoded
92→ENOPROTOOPT/EINVALmacros ✓ WSAEOPNOTSUPP→ENOTSUPmapping in windows_errno.zig ✓
Gate 5: Bot convergence ✅
5 review threads (coderabbit + claude[bot]) — all resolved. Addressed: hardcoded port fix, describe.concurrent, IPV6_V6ONLY leak (pre-existing, out of scope), error callback handling, WSAEOPNOTSUPP mapping.
Gate 6: Hygiene ✅
Branch farm/4cd4470b/fix-dgram-implicit-bind — correct format. PR body is thorough with context, test plan, and issue link.
Verdict: Ready for human review. Suggesting @cirospaciari as reviewer (most active non-bot contributor to bun-usockets).
There was a problem hiding this comment.
LGTM — the Windows crash bug I found was fixed, all reviewer comments are resolved, and the C-layer fixes are correct and well-scoped.
Extended reasoning...
Overview
This PR fixes three bugs in bsd_create_udp_socket() in packages/bun-usockets/src/bsd.c: (1) SO_REUSEPORT guard changed from Linux-only to availability-based, (2) fd leak + missing errno on bsd_set_reuse() failure path, (3) hardcoded errno 92 replaced with ENOPROTOOPT/EINVAL macros. A Windows errno mapping (WSAEOPNOTSUPP => ENOTSUP) was added in src/errno/windows_errno.zig to fix a crash I found in my previous review. A new test file with 5 regression tests covers the implicit bind-on-send behavior.
Security risks
No security risks. The changes are socket option configuration and error handling improvements. No auth, crypto, or permission-related code is touched.
Level of scrutiny
Medium. While this touches C socket infrastructure code, the changes are mechanical: a preprocessor guard fix, adding cleanup to an error path (matching the existing pattern used elsewhere in the function), replacing magic numbers with named constants, and adding a single line to an errno mapping switch. The crash bug I found in my previous review (WSAEOPNOTSUPP) was promptly fixed and the fix is a one-line addition to an existing mapping table.
Other factors
All reviewer comments (from me and CodeRabbit) have been addressed and resolved. The test file covers 5 scenarios for dgram implicit bind behavior. The PR has a claude label indicating it was generated by an automated system, but the fixes are straightforward and correct. The pre-existing IPV6_V6ONLY fd leak I noted is acknowledged as out of scope.
## Summary Fixes three bugs in `bsd_create_udp_socket()` in uSockets that affect macOS dgram socket behavior: - **`bsd_set_reuseport()` was Linux-only**: Changed `#if defined(__linux__)` to `#if defined(SO_REUSEPORT) && !defined(_WIN32)` so `reusePort: true` works on macOS - **Socket fd leak + missing errno on `bsd_set_reuse()` failure**: Added `bsd_close_socket()` and errno propagation so failures produce diagnostic error messages instead of generic "Failed to bind socket" - **Hardcoded errno 92 (Linux ENOPROTOOPT)**: Replaced with `ENOPROTOOPT` macro so IPv4 fallbacks for `IP_PKTINFO` and `IP_RECVTOS` are correctly attempted on macOS (where ENOPROTOOPT is 42, not 92) Also adds regression tests for the implicit bind-on-send behavior reported in oven-sh#28083, covering basic send-without-bind, listening event emission, multiple queued sends, short-form send, and bidirectional communication (k-rpc pattern). ### Context The reporter is on macOS (Darwin arm64, M4 Mac) and reports that calling `send()` on an unbound dgram socket silently fails to bind in Bun 1.3. This cannot be reproduced on Linux — the implicit bind code path works correctly there. The C-layer fixes in this PR address macOS-specific issues in the socket creation path that could cause silent failures or missing error diagnostics on that platform. Closes oven-sh#28083 ## Test plan - [x] `bun bd test test/regression/issue/28083.test.ts` — 5 pass - [x] Tests cover: implicit bind delivery, listening event, multiple queued sends, short-form send args, bidirectional k-rpc pattern - [x] C-layer fixes verified by code review (errno, fd leak, SO_REUSEPORT guard) --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary Fixes three bugs in `bsd_create_udp_socket()` in uSockets that affect macOS dgram socket behavior: - **`bsd_set_reuseport()` was Linux-only**: Changed `#if defined(__linux__)` to `#if defined(SO_REUSEPORT) && !defined(_WIN32)` so `reusePort: true` works on macOS - **Socket fd leak + missing errno on `bsd_set_reuse()` failure**: Added `bsd_close_socket()` and errno propagation so failures produce diagnostic error messages instead of generic "Failed to bind socket" - **Hardcoded errno 92 (Linux ENOPROTOOPT)**: Replaced with `ENOPROTOOPT` macro so IPv4 fallbacks for `IP_PKTINFO` and `IP_RECVTOS` are correctly attempted on macOS (where ENOPROTOOPT is 42, not 92) Also adds regression tests for the implicit bind-on-send behavior reported in oven-sh#28083, covering basic send-without-bind, listening event emission, multiple queued sends, short-form send, and bidirectional communication (k-rpc pattern). ### Context The reporter is on macOS (Darwin arm64, M4 Mac) and reports that calling `send()` on an unbound dgram socket silently fails to bind in Bun 1.3. This cannot be reproduced on Linux — the implicit bind code path works correctly there. The C-layer fixes in this PR address macOS-specific issues in the socket creation path that could cause silent failures or missing error diagnostics on that platform. Closes oven-sh#28083 ## Test plan - [x] `bun bd test test/regression/issue/28083.test.ts` — 5 pass - [x] Tests cover: implicit bind delivery, listening event, multiple queued sends, short-form send args, bidirectional k-rpc pattern - [x] C-layer fixes verified by code review (errno, fd leak, SO_REUSEPORT guard) --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Summary
Fixes three bugs in
bsd_create_udp_socket()in uSockets that affect macOS dgram socket behavior:bsd_set_reuseport()was Linux-only: Changed#if defined(__linux__)to#if defined(SO_REUSEPORT) && !defined(_WIN32)soreusePort: trueworks on macOSbsd_set_reuse()failure: Addedbsd_close_socket()and errno propagation so failures produce diagnostic error messages instead of generic "Failed to bind socket"ENOPROTOOPTmacro so IPv4 fallbacks forIP_PKTINFOandIP_RECVTOSare correctly attempted on macOS (where ENOPROTOOPT is 42, not 92)Also adds regression tests for the implicit bind-on-send behavior reported in #28083, covering basic send-without-bind, listening event emission, multiple queued sends, short-form send, and bidirectional communication (k-rpc pattern).
Context
The reporter is on macOS (Darwin arm64, M4 Mac) and reports that calling
send()on an unbound dgram socket silently fails to bind in Bun 1.3. This cannot be reproduced on Linux — the implicit bind code path works correctly there. The C-layer fixes in this PR address macOS-specific issues in the socket creation path that could cause silent failures or missing error diagnostics on that platform.Closes #28083
Test plan
bun bd test test/regression/issue/28083.test.ts— 5 pass