Skip to content

Commit 81a26ea

Browse files
authored
v1.2.4
Merge pull request #4 from jacobdwyer16/fix/wsl-timeout - Added timeout to WSL credential lookups
2 parents 5e039fa + e517eb9 commit 81a26ea

File tree

1 file changed

+43
-20
lines changed

1 file changed

+43
-20
lines changed

src/poller.rs

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,27 @@ fn cli_refresh_wsl_token(distro: &str) {
131131
wait_for_refresh(&mut child);
132132
}
133133

134+
/// Spawn a command and wait up to `timeout` for it to finish.
135+
/// Returns None if the process fails to start or exceeds the deadline.
136+
fn run_with_timeout(cmd: &mut Command, timeout: Duration) -> Option<std::process::Output> {
137+
let mut child = cmd.spawn().ok()?;
138+
let start = std::time::Instant::now();
139+
loop {
140+
match child.try_wait() {
141+
Ok(Some(_)) => return child.wait_with_output().ok(),
142+
Ok(None) => {
143+
if start.elapsed() > timeout {
144+
let _ = child.kill();
145+
let _ = child.wait();
146+
return None;
147+
}
148+
std::thread::sleep(Duration::from_millis(100));
149+
}
150+
Err(_) => return None,
151+
}
152+
}
153+
}
154+
134155
fn wait_for_refresh(child: &mut std::process::Child) {
135156
// Wait up to 30 seconds; don't block the poll thread forever.
136157
let start = std::time::Instant::now();
@@ -382,18 +403,19 @@ fn read_credentials_from_source(source: &CredentialSource) -> Option<Credentials
382403
}
383404

384405
fn read_wsl_credentials(distro: &str) -> Option<Credentials> {
385-
let output = Command::new("wsl.exe")
386-
.arg("-d")
387-
.arg(distro)
388-
.arg("--")
389-
.arg("sh")
390-
.arg("-lc")
391-
.arg("cat ~/.claude/.credentials.json")
392-
.creation_flags(CREATE_NO_WINDOW)
393-
.stdout(std::process::Stdio::piped())
394-
.stderr(std::process::Stdio::null())
395-
.output()
396-
.ok()?;
406+
let output = run_with_timeout(
407+
Command::new("wsl.exe")
408+
.arg("-d")
409+
.arg(distro)
410+
.arg("--")
411+
.arg("sh")
412+
.arg("-lc")
413+
.arg("cat ~/.claude/.credentials.json")
414+
.creation_flags(CREATE_NO_WINDOW)
415+
.stdout(std::process::Stdio::piped())
416+
.stderr(std::process::Stdio::null()),
417+
Duration::from_secs(5),
418+
)?;
397419

398420
if !output.status.success() {
399421
return None;
@@ -435,14 +457,15 @@ fn choose_best_credentials(mut candidates: Vec<Credentials>) -> Option<Credentia
435457
}
436458

437459
fn list_wsl_distros() -> Vec<String> {
438-
let output = match Command::new("wsl.exe")
439-
.args(["-l", "-q"])
440-
.creation_flags(CREATE_NO_WINDOW)
441-
.stdout(std::process::Stdio::piped())
442-
.stderr(std::process::Stdio::null())
443-
.output()
444-
{
445-
Ok(output) if output.status.success() => output,
460+
let output = match run_with_timeout(
461+
Command::new("wsl.exe")
462+
.args(["-l", "-q"])
463+
.creation_flags(CREATE_NO_WINDOW)
464+
.stdout(std::process::Stdio::piped())
465+
.stderr(std::process::Stdio::null()),
466+
Duration::from_secs(5),
467+
) {
468+
Some(output) if output.status.success() => output,
446469
_ => return Vec::new(),
447470
};
448471

0 commit comments

Comments
 (0)