fix(core): fallback to child_process for WSL Windows binaries to prevent hang#19173
fix(core): fallback to child_process for WSL Windows binaries to prevent hang#19173hsm207 wants to merge 2 commits intogoogle-gemini:mainfrom
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Summary of ChangesHello @hsm207, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a critical deadlock issue encountered when executing Windows binaries via WSL in a pseudo-terminal (PTY). The solution involves intelligently identifying such scenarios and gracefully falling back to standard child process execution, thereby bypassing the PTY-related hang caused by unhandled cursor position requests. This ensures smoother and more reliable command execution in WSL environments. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request aims to fix a critical deadlock when running Windows binaries on WSL through a PTY. The approach of detecting the binary and falling back to child_process is correct. However, the current implementation uses a path-based regex to detect Windows binaries, which is not robust. It will fail for users with custom WSL mount configurations, leaving them exposed to the original hang. I've suggested a more reliable method based on checking the file's magic bytes, which would make the fix comprehensive.
| if (/^\/mnt\/[a-z]\//.test(realPath)) { | ||
| debugLogger.log('WSL Windows binary detected, disabling PTY'); | ||
| shouldUseNodePty = false; | ||
| } |
There was a problem hiding this comment.
The regex /^\/mnt\/[a-z]\// for detecting Windows binaries in WSL is brittle. It will not work for users with custom WSL mount configurations (e.g., mounting C: at /c via /etc/wsl.conf), and it could cause false positives for valid Linux paths like /mnt/a/some/dir. This means the "critical deadlock" this PR aims to fix will still occur for users with non-default configurations.
A more robust approach is to check the file's magic number to identify it as a Windows PE executable (MZ at the beginning of the file). This is independent of the file's path.
Here is an example of how you could implement this check:
async function isWindowsExecutable(filePath: string): Promise<boolean> {
try {
const buffer = Buffer.alloc(2);
const fd = await fs.promises.open(filePath, 'r');
await fd.read(buffer, 0, 2, 0);
await fd.close();
// Check for 'MZ' magic number
return buffer.toString() === 'MZ';
} catch {
return false;
}
}You could then use if (await isWindowsExecutable(realPath)) instead of the regex test. When calling isWindowsExecutable, ensure filePath is a resolved path (e.g., using fs.promises.realpath) to prevent potential path traversal vulnerabilities. Also, remember to import the fs module using the node: prefix (e.g., import * as fs from 'node:fs';). It would be best to place this helper function in a utility file.
Note that the test should force child_process when detecting WSL Windows binary will also need to be updated to support this, likely by mocking fs.promises.open and fs.promises.read to return the MZ magic bytes for the given path.
async function isWindowsExecutable(filePath: string): Promise<boolean> {
try {
const buffer = Buffer.alloc(2);
const fd = await fs.promises.open(filePath, 'r');
await fd.read(buffer, 0, 2, 0);
await fd.close();
// Check for 'MZ' magic number
return buffer.toString() === 'MZ';
} catch {
return false;
}
}References
- When requesting file access permissions, resolve symbolic links first to display the actual path being accessed, preventing potential path traversal vulnerabilities.
- Use the
node:prefix when importing built-in Node.js modules for consistency across the codebase.
There was a problem hiding this comment.
Thanks for the feedback! I've refactored the detection logic to follow the suggested 'MZ' magic byte approach. I've also flattened the implementation using guard clauses and modern async patterns, and encapsulated it within a private helper method (isWslWindowsBinary) inside ShellExecutionService. Updated the tests to verify the magic byte detection works correctly.
5744bee to
fecb8d8
Compare
ebe86f8 to
114bcba
Compare
Summary
Fixes a critical deadlock where running Windows binaries (like
pwsh.exe) via WSL in a PTY causes an indefinite hang due to unanswered Cursor Position Requests (\u001b[6n).Details
Detects if a command resolves to a Windows path (e.g.,
/mnt/c/...) on Linux and forces a fallback tochild_process(standard pipes) instead of usingnode-pty. This ensures that interactive-only escape sequences are not triggered or expected.Related Issues
Fixes #15233
How to Validate
Run
gemini -p "pwsh --version"in a WSL environment.Pre-Merge Checklist