Skip to content

net: support sending net.BoundSocket to worker threads and child processes - #64725

Open
guybedford wants to merge 1 commit into
nodejs:mainfrom
guybedford:boundsocket-transfer
Open

net: support sending net.BoundSocket to worker threads and child processes#64725
guybedford wants to merge 1 commit into
nodejs:mainfrom
guybedford:boundsocket-transfer

Conversation

@guybedford

@guybedfordguybedford commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

This adds support for transferring net.BoundSocket instances to other threads via the worker_threadspostMessage() transfer list, and for sending them to child processes as the sendHandle argument of subprocess.send(), following on from #64399 and #64460.

A BoundSocket reserves a port synchronously at construction time. Making it transferable means a port can be reserved on one thread or process and the bound handle handed off to another to listen or connect on, without racing on the bind.

  • BoundSocket implements [kTransfer]/[kTransferList]/[kDeserialize], moving the underlying TCP handle with the same mechanism used for net.Socket and net.Server transfer.
  • subprocess.send()/process.send() accept a BoundSocket as sendHandle: the handleConversion entry reuses the transfer protocol on the sending side and the _TransferredBoundSocket deserialization path on the receiving side. The transport is the same as cluster's shared-handle scheduling (SCM_RIGHTS on Unix, WSADuplicateSocket on Windows), both of which carry bind state.
  • After transfer or send, the source instance behaves as if adopted: address(), fd() and close() throw ERR_SOCKET_HANDLE_ADOPTED.
  • Transfer requires an un-adopted, open TCP handle, otherwise ERR_WORKER_HANDLE_NOT_TRANSFERABLE is thrown. Pipe (path) binds are not transferable, and throw ERR_INVALID_HANDLE_TYPE when sent over IPC.
  • On the receiving side the local address is re-derived from the handle rather than trusted from serialized state.

Tests cover a parent-to-worker transfer and a parent-to-child-process send where the receiver listens on the transferred bind, plus guard cases (closed, adopted and pipe-bound sockets). Docs updated in net.md, worker_threads.md, child_process.md and errors.md.

@nodejs-github-bot

Copy link
Copy Markdown
Collaborator

Review requested:

  • @nodejs/net

@nodejs-github-botnodejs-github-bot added needs-ci PRs that need a full CI run. net Issues and PRs related to the net subsystem. labels Jul 25, 2026
@guybedfordguybedford changed the title net: support transferring net.BoundSocket to other threadsnet: support transferring net.BoundSocket to worker threadsJul 25, 2026
@guybedford
guybedfordforce-pushed the boundsocket-transfer branch from 88e7187 to 1fefa08CompareJuly 25, 2026 01:48
@codecov

codecovBot commented Jul 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.07143% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.14%. Comparing base (b420cb6) to head (b21b5f1).
⚠️ Report is 24 commits behind head on main.

Files with missing linesPatch %Lines
lib/net.js89.06%7 Missing ⚠️
lib/internal/child_process.js93.75%3 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #64725 +/- ##
========================================
Coverage 90.13% 90.14% ========================================
Files 743 744 +1 Lines 242412 242612 +200 Branches 45655 45697 +42 ========================================
+ Hits 218510 218693 +183 - Misses 15403 15418 +15 - Partials 8499 8501 +2 
Files with missing linesCoverage Δ
lib/internal/child_process.js94.87% <93.75%> (+0.13%)⬆️
lib/net.js94.50% <89.06%> (+0.07%)⬆️

... and 36 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mcollinamcollina left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@guybedford
guybedfordforce-pushed the boundsocket-transfer branch from 1fefa08 to d5b711dCompareJuly 27, 2026 19:39
@guybedfordguybedford changed the title net: support transferring net.BoundSocket to worker threadsnet: support sending net.BoundSocket to worker threads and child processesJul 27, 2026
@guybedford

Copy link
Copy Markdown
ContributorAuthor

I've updated this PR to also include support for transferring a BoundSocket to a child process.

This adds support for transferring net.BoundSocket instances to other
threads via the worker_threads postMessage() transfer list, and for
sending them to child processes as the sendHandle argument of
subprocess.send(), following on from the BoundSocket introduction.
A BoundSocket reserves a port synchronously at construction time.
Making it transferable means a port can be reserved on one thread or
process and the bound (but not yet listening or connected) TCP handle
handed off to another to listen or connect on, without racing on the
bind.
For threads, BoundSocket implements kTransfer/kTransferList/
kDeserialize, moving the underlying TCP handle with the same mechanism
used for net.Socket and net.Server transfer. For child processes, the
handleConversion entry reuses the same transfer protocol on the
sending side and the same _TransferredBoundSocket deserialization path
on the receiving side; the underlying transport is that of cluster's
shared-handle scheduling: SCM_RIGHTS on Unix and WSADuplicateSocket on
Windows, both of which carry bind state.
In both cases the source instance is left in the adopted state:
address(), fd() and close() throw ERR_SOCKET_HANDLE_ADOPTED. Transfer
requires an un-adopted, open TCP handle, otherwise
ERR_WORKER_HANDLE_NOT_TRANSFERABLE is thrown; pipe (path) binds are
not transferable and throw ERR_INVALID_HANDLE_TYPE when sent over IPC.
On the receiving side the local address is re-derived from the handle
rather than trusted from serialized state.
Signed-off-by: Guy Bedford <guybedford@gmail.com>
@guybedford
guybedfordforce-pushed the boundsocket-transfer branch 2 times, most recently from b21b5f1 to c05f5f9CompareJuly 27, 2026 21:02
@guybedfordguybedford changed the title net: support sending net.BoundSocket to worker threads and child processesnet: support sending BoundSocket and pipe sockets to threads and child processesJul 27, 2026
@guybedford
guybedfordforce-pushed the boundsocket-transfer branch from c05f5f9 to b21b5f1CompareJuly 27, 2026 21:05
@guybedfordguybedford changed the title net: support sending BoundSocket and pipe sockets to threads and child processesnet: support sending net.BoundSocket to worker threads and child processesJul 27, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ciPRs that need a full CI run.netIssues and PRs related to the net subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@guybedford@nodejs-github-bot@mcollina