mirror of
https://github.com/wez/wezterm.git
synced 2024-11-22 22:42:48 +03:00
pty: don't try to spawn a directory from the cwd
When the cwd was set to a directory that contained an executable directory whose name matched the argv0 of the command to be spawned, we'd incorrectly consider that to be a valid candidate. When later trying to spawn this, we'll fail with an EACCESS, and in the context of wezterm, rust's internal error handling machinery for this error would fail to write to a descriptor because our close_random_fds() function has closed that descriptor during pre_exec. That in turn would cause rust to print a panic message to the output stream of this semi-spawned process, which would show briefly an error message with no useful context. This commit resolves this issue by explicitly avoiding executable directories in this case. refs: https://github.com/wez/wezterm/issues/4920
This commit is contained in:
parent
aa94a98314
commit
17dadbeb1e
@ -32,6 +32,9 @@ As features stabilize some brief notes about them will accumulate here.
|
||||
attributes. #4808
|
||||
* Changing the palette via escape sequences didn't invalidate caches
|
||||
correctly, so those escapes sequences wouldn't take effect. #4932 #2635
|
||||
* Unix: spawning a command using a relative path, with the cwd set to a
|
||||
directory that contains a directory with the same name as the relative
|
||||
path to the command would fail with an obscure error message. #4920
|
||||
|
||||
### 20240128-202157-1e552d76
|
||||
|
||||
|
@ -422,38 +422,45 @@ impl CommandBuilder {
|
||||
|
||||
let mut errors = vec![];
|
||||
|
||||
if access(&abs_path, AccessFlags::X_OK).is_ok() {
|
||||
if abs_path.is_dir() {
|
||||
errors.push(format!("{} exists but is a directory", abs_path.display()));
|
||||
} else if access(&abs_path, AccessFlags::X_OK).is_ok() {
|
||||
return Ok(abs_path.into_os_string());
|
||||
}
|
||||
if access(&abs_path, AccessFlags::F_OK).is_ok() {
|
||||
} else if access(&abs_path, AccessFlags::F_OK).is_ok() {
|
||||
errors.push(format!(
|
||||
"{} exists but is not executable",
|
||||
abs_path.display()
|
||||
));
|
||||
} else {
|
||||
if let Some(path) = self.resolve_path() {
|
||||
for path in std::env::split_paths(&path) {
|
||||
let candidate = path.join(&exe);
|
||||
if access(&candidate, AccessFlags::X_OK).is_ok() {
|
||||
return Ok(candidate.into_os_string());
|
||||
}
|
||||
if access(&candidate, AccessFlags::F_OK).is_ok() {
|
||||
errors.push(format!(
|
||||
"{} exists but is not executable",
|
||||
candidate.display()
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(path) = self.resolve_path() {
|
||||
for path in std::env::split_paths(&path) {
|
||||
let candidate = path.join(&exe);
|
||||
|
||||
if candidate.is_dir() {
|
||||
errors.push(format!("{} exists but is a directory", candidate.display()));
|
||||
} else if access(&candidate, AccessFlags::X_OK).is_ok() {
|
||||
return Ok(candidate.into_os_string());
|
||||
} else if access(&candidate, AccessFlags::F_OK).is_ok() {
|
||||
errors.push(format!(
|
||||
"{} exists but is not executable",
|
||||
candidate.display()
|
||||
));
|
||||
}
|
||||
errors.push(format!("No viable candidates found in PATH {path:?}"));
|
||||
} else {
|
||||
errors.push("Unable to resolve the PATH".to_string());
|
||||
}
|
||||
errors.push(format!("No viable candidates found in PATH {path:?}"));
|
||||
} else {
|
||||
errors.push("Unable to resolve the PATH".to_string());
|
||||
}
|
||||
anyhow::bail!(
|
||||
"Unable to spawn {} because:\n{}",
|
||||
exe_path.display(),
|
||||
errors.join(".\n")
|
||||
);
|
||||
} else if exe_path.is_dir() {
|
||||
anyhow::bail!(
|
||||
"Unable to spawn {} because it is a directory",
|
||||
exe_path.display()
|
||||
);
|
||||
} else {
|
||||
if let Err(err) = access(exe_path, AccessFlags::X_OK) {
|
||||
if access(exe_path, AccessFlags::F_OK).is_ok() {
|
||||
|
Loading…
Reference in New Issue
Block a user