perf(cli): drop the lsof port pre-flight from server-routed commands - #10673
Conversation
Every server-routed command spawned lsof twice (once to find the pid on the port, once to read that pid's cwd) to prove the server belongs to this workspace - ~309ms on every command. The request already proves it: each server writes its token into its own scope dir, so a port file pointing at another workspace's server gets a 401, and a dead port gets ECONNREFUSED. Both now drop the stale port file and fall back to running in-process. 590ms -> 281ms for a server-routed 'bit status'. The cli-server-port command keeps validating, since external clients rely on it reporting no port when there is no usable server.
PR Summary by QodoRemove lsof preflight from server-routed CLI commands
AI Description
Diagram
High-Level Assessment
Files changed (1)
|
Code Review by Qodo
1. Listener identity is unverified
|
Two reliability gaps from dropping the lsof pre-flight: - getExistingPort parsed the file with an unchecked parseInt, so an empty or half-written file became NaN and surfaced as an opaque fetch error that exited instead of falling back in-process. Validate it and fall back. The file is deliberately not deleted - a torn read means the server is mid-write. - A 401 was always treated as a stale port file, so a command spanning a server restart could delete the port file of a live server. Re-read the token first: the server publishes it before registering routes, so if it changed this is a restart and the request is simply retried.
|
Code review by qodo was updated up to the latest commit 8b472f6 |
A listener that inherited a stale port could answer the request with any JSON
and have it reported as the command's output, suppressing the real command.
bit-server always returns a { data, exitCode } object, so anything else now
fails safe: drop the port file and run the command in-process.
|
Code review by qodo was updated up to the latest commit 19eb957 |
Every command routed through bit-server spawned
lsoftwice before sending anything: once to find the pid listening on the port, then once more (orreadlink /proc/<pid>/cwdon Linux) to read that pid's cwd and confirm the server belongs to this workspace. That is ~320ms of subprocess overhead on every command, and it directly affects VS Code extension latency.The request already proves what the pre-flight was checking. Each server writes its bearer token into its own scope dir, so a port file left pointing at another workspace's server fails the token check and comes back 401; a dead port gives ECONNREFUSED. Both drop the stale port file and throw
ServerIsNotRunning, whichrun-bit.tsalready catches to fall back to running the command in-process — the same outcome the lsof check produced, minus the two spawns.Measured
Server-routed
bit status, median of 7, same workspace and machine, both arms compiled and measured back to back:~322ms / 51% per command.
Reliability (from review)
Removing the pre-flight lost a few things it was doing incidentally, all since restored:
lsof -iTCP:NaNused to fail and route an unparseable port file into the in-process fallback.getExistingPort()now validates the parsed value explicitly. It deliberately does not delete the file — a torn read means the server is mid-write, and deleting would destroy a port file about to become valid (master deletes it today, so this is now strictly better).writeServerToken()runs before any route is registered, so a server able to answer with a 401 has already published its current token.{ data, exitCode }object; anything else now fails safe by dropping the port file and running in-process.Behavior checks
Note on server authentication
bit-server authenticates the client to the server but never the server to the client. That is pre-existing and platform-wide: on Windows
getCwdByPidreturns null, soisPortInUseForCurrentDiralready returned true for any listener. The cwd comparison this PR removes was not an authentication mechanism either — cwd is attacker-controlled, since anyone able to bind the port can alsocdinto the workspace. Proper server-to-client auth (e.g. an HMAC over a client nonce) is worth doing on its own; it isn't something this change makes newly necessary.cli-server-portkeeps the full lsof validation. Its job is to answer "is there a usable server?" for external clients like the VS Code extension, which expect no output when there isn't one, so the two spawns are worth it for that one rarely-called command.