Skip to content

Comments

Make normalizeSpawn truly async to prevent event loop blocking#55

Draft
Copilot wants to merge 4 commits intobranch-4-devtestfrom
copilot/sub-pr-54
Draft

Make normalizeSpawn truly async to prevent event loop blocking#55
Copilot wants to merge 4 commits intobranch-4-devtestfrom
copilot/sub-pr-54

Conversation

Copy link
Contributor

Copilot AI commented Feb 14, 2026

The normalizeSpawn function in launch.ts returned a synchronous wrapper that called spawnSync, blocking the event loop during async runLaunch preflight checks.

Changes

  • Replaced spawnSync with async spawn — Added spawnAsync helper that wraps child_process.spawn in a Promise, collecting stdout/stderr via streams without blocking
  • Updated type signatures — Changed DoctorDependencies.spawnCommand to return Promise<...>
  • Awaited all spawn calls — Added await to preflight check, codex auth, and MCP registration flows in both launch.ts and doctor.ts
  • Updated test mocks — Made all spawnCommand test doubles async

Implementation

The spawnAsync wrapper always resolves (never rejects) to match spawnSync API contract, communicating errors via status code and stderr:

function spawnAsync(
  command: string,
  args: string[],
  options: { cwd: string; encoding: BufferEncoding }
): Promise<Pick<SpawnSyncReturns<string>, 'status' | 'stdout' | 'stderr'>> {
  return new Promise((resolve) => {
    const child = spawn(command, args, { cwd: options.cwd, stdio: ['ignore', 'pipe', 'pipe'] });
    // ... collect stdout/stderr asynchronously
    child.on('close', (code) => resolve({ status: code ?? 0, stdout, stderr }));
    child.on('error', (error) => resolve({ status: 1, stdout, stderr: error.message }));
  });
}

This preserves existing error handling patterns while eliminating event loop blocking.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits February 14, 2026 13:21
- Update DoctorDependencies.spawnCommand to return Promise
- Update LaunchDependencies (extends DoctorDependencies)
- Modify normalizeSpawn to return async wrapper function
- Await all spawnCommand calls in launch.ts (preflight, auth, mcp registration)
- Await all spawnCommand calls in doctor.ts (cli help, login status, mcp list)
- Update launch.test.ts with async spawnCommand mocks
- Update doctor.test.ts with async spawnCommand mocks
- All tests pass (9/9)

Co-authored-by: clduab11 <185000089+clduab11@users.noreply.github.com>
Replace wrapped spawnSync with proper async spawn implementation:
- Add spawnAsync helper using child_process.spawn with Promise
- Update doctor.ts to use spawnAsync by default
- Update launch.ts to use spawnAsync by default
- Prevents actual event loop blocking (not just wrapping sync in async)
- All tests still pass (9/9)

Co-authored-by: clduab11 <185000089+clduab11@users.noreply.github.com>
Document that spawnAsync always resolves (never rejects) to match spawnSync API:
- Errors communicated via status code and stderr
- Matches expected behavior of calling code
- Prevents unnecessary try/catch blocks in callers
- All tests still pass (9/9)

Co-authored-by: clduab11 <185000089+clduab11@users.noreply.github.com>
Copilot AI changed the title [WIP] Add launch orchestrator and docker auth support Make normalizeSpawn truly async to prevent event loop blocking Feb 14, 2026
Copilot AI requested a review from clduab11 February 14, 2026 13:25
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