diff --git a/CHANGELOG.md b/CHANGELOG.md index db199d84..6ed72ade 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its ### Fixed - Modifiers being out of sync for fast/synthetic input on X11 +- Child process creation failing while inside a deleted directory ## 0.15.0 diff --git a/alacritty/src/daemon.rs b/alacritty/src/daemon.rs index c8fb88d1..fa530fa0 100644 --- a/alacritty/src/daemon.rs +++ b/alacritty/src/daemon.rs @@ -9,6 +9,7 @@ use std::process::{Command, Stdio}; #[rustfmt::skip] #[cfg(not(windows))] use { + std::env, std::error::Error, std::os::unix::process::CommandExt, std::os::unix::io::RawFd, @@ -58,18 +59,22 @@ where { let mut command = Command::new(program); command.args(args).stdin(Stdio::null()).stdout(Stdio::null()).stderr(Stdio::null()); - if let Ok(cwd) = foreground_process_path(master_fd, shell_pid) { - command.current_dir(cwd); - } + + let working_directory = foreground_process_path(master_fd, shell_pid).ok(); unsafe { command - .pre_exec(|| { + .pre_exec(move || { match libc::fork() { -1 => return Err(io::Error::last_os_error()), 0 => (), _ => libc::_exit(0), } + // Copy foreground process' working directory, ignoring invalid paths. + if let Some(working_directory) = working_directory.as_ref() { + let _ = env::set_current_dir(working_directory); + } + if libc::setsid() == -1 { return Err(io::Error::last_os_error()); } diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 888bec4f..c761f5ae 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -844,9 +844,8 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon #[cfg(not(windows))] fn create_new_window(&mut self, #[cfg(target_os = "macos")] tabbing_id: Option) { let mut options = WindowOptions::default(); - if let Ok(working_directory) = foreground_process_path(self.master_fd, self.shell_pid) { - options.terminal_options.working_directory = Some(working_directory); - } + options.terminal_options.working_directory = + foreground_process_path(self.master_fd, self.shell_pid).ok(); #[cfg(target_os = "macos")] { @@ -875,7 +874,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon match result { Ok(_) => debug!("Launched {} with args {:?}", program, args), - Err(_) => warn!("Unable to launch {} with args {:?}", program, args), + Err(err) => warn!("Unable to launch {program} with args {args:?}: {err}"), } } diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 6565f20b..e3db51fb 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -231,6 +231,7 @@ pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd builder.env_remove("XDG_ACTIVATION_TOKEN"); builder.env_remove("DESKTOP_STARTUP_ID"); + let working_directory = config.working_directory.clone(); unsafe { builder.pre_exec(move || { // Create a new process group. @@ -239,6 +240,11 @@ pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd return Err(Error::new(ErrorKind::Other, "Failed to set session id")); } + // Set working directory, ignoring invalid paths. + if let Some(working_directory) = working_directory.as_ref() { + let _ = env::set_current_dir(working_directory); + } + set_controlling_terminal(slave_fd); // No longer need slave/master fds. @@ -256,11 +262,6 @@ pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd }); } - // Handle set working directory option. - if let Some(dir) = &config.working_directory { - builder.current_dir(dir); - } - // Prepare signal handling before spawning child. let (signals, sig_id) = { let (sender, recv) = UnixStream::pair()?;