Skip to content

[Inspector] Socket backend: don't initialize the socket library when the RemoteInspector singleton is created - #470

Open
dylan-conway wants to merge 2 commits into
mainfrom
claude/inspector-socket-lazy-init
Open

dylan-conway wants to merge 2 commits into
mainfrom
claude/inspector-socket-lazy-init

Conversation

@dylan-conway

Copy link
Copy Markdown
Member

With ENABLE(REMOTE_INSPECTOR) and the socket backend, RemoteInspector::singleton() is constructed the first time any JSGlobalObject is created (JSGlobalObjectDebuggable::initRemoteControllableTarget::initregisterTarget), and its constructor called Socket::init(). On Windows that is WSAStartup(), which loads ws2_32 and friends — about 0.75 ms of every Bun process start (6.3 samples at 8 kHz under JSGlobalObject::init), whether or not an inspector server or client ever exists.

RemoteInspectorSocketEndpoint already calls Socket::init() in its constructor, and every socket operation the inspector performs goes through the endpoint singleton, so the call in the RemoteInspector constructor is redundant. This removes it; start() (which only flips m_enabled) stays.

…the RemoteInspector singleton is created

RemoteInspector::singleton() is constructed the first time any JSGlobalObject
is created (JSGlobalObjectDebuggable -> RemoteControllableTarget::init), and
its constructor called Socket::init(). On Windows that is WSAStartup(), which
loads ws2_32/mswsock and costs the better part of a millisecond in every
process, whether or not an inspector server or client ever exists.

RemoteInspectorSocketEndpoint already calls Socket::init() when it is
created, and every socket operation goes through the endpoint, so the call
in the constructor is redundant.
@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your current included review allowance is based on your included PR review attempts over the past 7 days.

Next review available in: 24 minutes

Limit details: You’ve used the included review currently available. Your 61 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 30e57551-6ffc-4dc1-b062-fd9e28a95301

📥 Commits

Reviewing files that changed from the base of the PR and between 18c3194 and 036582a.

📒 Files selected for processing (1)
  • Source/JavaScriptCore/inspector/remote/socket/RemoteInspectorSocket.cpp

Comment @coderabbitai help to get the list of available commands.

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM — removing the redundant Socket::init() from the RemoteInspector constructor is safe and saves the WSAStartup cost on every process start.

What was reviewed:

  • Confirmed RemoteInspectorSocketEndpoint::RemoteInspectorSocketEndpoint() still calls Socket::init() before any socket use.
  • Verified all RemoteInspectorConnectionClient socket paths (connectInet, createClient, send, dtor) go through the endpoint singleton, so init is guaranteed before first socket op.
  • RemoteInspectorServer has its own Socket::init(), so the server path is also covered independently.
Extended reasoning...

Overview

Single-line functional change in Source/JavaScriptCore/inspector/remote/socket/RemoteInspectorSocket.cpp: the Socket::init() call is removed from RemoteInspector::RemoteInspector() and replaced with an explanatory comment. The constructor now only calls start(), which just sets m_enabled = true under a lock.

Security risks

None. This is initialization ordering for the platform socket library (WSAStartup on Windows, no-op on POSIX). No auth, crypto, permissions, or user-controlled data is involved. The only theoretical risk would be a socket call before WSAStartup, which is ruled out below.

Level of scrutiny

Low. The change is a one-line deletion in the remote-inspector socket backend, guarded by ENABLE(REMOTE_INSPECTOR). The correctness argument is easy to verify statically:

  • RemoteInspector inherits from RemoteInspectorConnectionClient, and every socket-touching method on that base (connectInet, createClient, send, and the destructor's invalidateClient) first obtains RemoteInspectorSocketEndpoint::singleton().
  • RemoteInspectorSocketEndpoint's constructor calls Socket::init() as its first statement (RemoteInspectorSocketEndpoint.cpp:55), before creating the wakeup socket pair and worker thread.
  • RemoteInspectorServer separately calls Socket::init() in its own constructor, so the listen path is covered too.
  • WSAStartup is reference-counted, so dropping one redundant caller is harmless even when the inspector is used.

Therefore no socket API can be reached without Socket::init() having run, and the removed call was strictly redundant.

Other factors

The PR description gives a clear, measured motivation (~0.75 ms of Bun startup on Windows via JSGlobalObject::initRemoteControllableTarget::initregisterTarget). The remaining start() call is unchanged and does no I/O. No prior human review comments or outstanding requests on the PR. The bug-hunting system found no issues.

@github-actions

github-actions Bot commented Aug 18, 2026

Copy link
Copy Markdown

Preview Builds

Commit Release Date
036582a6 autobuild-preview-pr-470-036582a6 2026-08-18 23:18:46 UTC
41acf981 autobuild-preview-pr-470-41acf981 2026-08-18 11:35:01 UTC

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM — removing the redundant Socket::init() call is safe since RemoteInspectorSocketEndpoint already handles it.

What was reviewed:

  • Verified RemoteInspectorSocketEndpoint::RemoteInspectorSocketEndpoint() calls Socket::init() and all inspector socket ops (connectInet, createClient, send) route through the endpoint singleton.
  • Confirmed Socket::init() on Windows is std::once_flag-guarded, so the prior double-init was harmless but wasteful; start() does no socket work.
  • Checked that RemoteInspector::connect(ConnectionID) receives an ID minted by the endpoint, so the endpoint is always constructed first.
Extended reasoning...

Overview

This PR removes a single Socket::init() call from the RemoteInspector constructor in the socket-backend implementation (RemoteInspectorSocket.cpp) and replaces it with an explanatory comment. The motivation is startup performance: the RemoteInspector singleton is constructed on the first JSGlobalObject creation regardless of whether remote inspection is ever used, and on Windows Socket::init() calls WSAStartup(), costing ~0.75 ms per process start.

Security risks

None. This defers Winsock initialization; it does not change what is initialized or expose any new surface. The inspector socket path is unchanged in behavior once actually used.

Level of scrutiny

Low. This is a one-line deletion in debug/inspector infrastructure. The key correctness question is whether any socket operation can be reached without first constructing RemoteInspectorSocketEndpoint. I verified:

  • RemoteInspectorSocketEndpoint::RemoteInspectorSocketEndpoint() calls Socket::init() (line 55).
  • Every socket-touching path in RemoteInspectorConnectionClient (connectInet, createClient, send, destructor) and RemoteInspectorServer first calls RemoteInspectorSocketEndpoint::singleton().
  • RemoteInspector::start() only flips m_enabled under a lock — no socket work.
  • Socket::init() on Windows is guarded by std::once_flag, so the removed call was purely redundant, not load-bearing for ordering.

Other factors

The change is self-contained, the added comment accurately documents why the call was removed, and preview builds succeeded. No outstanding reviewer comments. The bug hunting system found no issues.

@Jarred-Sumner

Copy link
Copy Markdown
Collaborator

I think we can just compile without this.

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.

2 participants