diff options
author | Jesse Luehrs <doy@tozt.net> | 2022-01-09 22:06:06 -0500 |
---|---|---|
committer | Jesse Luehrs <doy@tozt.net> | 2022-01-09 22:06:06 -0500 |
commit | 819158c696c24b51f5881a8ea5e765fe21bb1b87 (patch) | |
tree | 0b521d71daec7036feed4d690447a5672e2b5b72 | |
parent | 7f2a0f4f3f232763822734562e2f44892ed31d1c (diff) | |
download | nbsh-819158c696c24b51f5881a8ea5e765fe21bb1b87.tar.gz nbsh-819158c696c24b51f5881a8ea5e765fe21bb1b87.zip |
block SIGTTOU when calling tcsetpgrp
otherwise it'll fail if the session leader is a background process
-rw-r--r-- | src/pipeline/mod.rs | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/src/pipeline/mod.rs b/src/pipeline/mod.rs index 7748b0e..b47d0d6 100644 --- a/src/pipeline/mod.rs +++ b/src/pipeline/mod.rs @@ -449,8 +449,33 @@ fn set_foreground_pg(pg: nix::unistd::Pid) -> anyhow::Result<()> { nix::fcntl::OFlag::empty(), nix::sys::stat::Mode::empty(), )?; - nix::unistd::tcsetpgrp(pty, pg)?; + + // if a background process calls tcsetpgrp, the kernel will send it + // SIGTTOU which suspends it. if that background process is the session + // leader and doesn't have SIGTTOU blocked, the kernel will instead just + // return ENOTTY from the tcsetpgrp call rather than sending a signal to + // avoid deadlocking the process. therefore, we need to ensure that + // SIGTTOU is blocked here. + + // Safety: setting a signal handler to SigIgn is always safe + unsafe { + nix::sys::signal::signal( + nix::sys::signal::Signal::SIGTTOU, + nix::sys::signal::SigHandler::SigIgn, + )?; + } + let res = nix::unistd::tcsetpgrp(pty, pg); + // Safety: setting a signal handler to SigDfl is always safe + unsafe { + nix::sys::signal::signal( + nix::sys::signal::Signal::SIGTTOU, + nix::sys::signal::SigHandler::SigDfl, + )?; + } + res?; + nix::unistd::close(pty)?; + nix::sys::signal::kill(neg_pid(pg), nix::sys::signal::Signal::SIGCONT) .or_else(|e| { // the process group has already exited @@ -460,6 +485,7 @@ fn set_foreground_pg(pg: nix::unistd::Pid) -> anyhow::Result<()> { Err(e) } })?; + Ok(()) } |