fix(child-process): unexpected pane closing issue with nushell (#648)

* fix unexpected pane closing issue with nushell

nushell doesn't create a new process group when spawnning a process,
so all processes including the ones spwanned by us are in the same
foreground group. So if kernel will send signal to every member of this
group.

This patch fixes this issue by creating a new foreground process group
when spawnning a new terminal pane.

Fix #615

Signed-off-by: Tw <tw19881113@gmail.com>

* add comment about unsafe

Co-authored-by: Aram Drevekenin <aram@poor.dev>
This commit is contained in:
Tw 2021-08-16 20:19:05 +08:00 committed by GitHub
parent da3f20c816
commit e477f3b5cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,5 +1,6 @@
use std::env; use std::env;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use std::os::unix::process::CommandExt;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::{Child, Command}; use std::process::{Child, Command};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
@ -102,10 +103,21 @@ fn handle_terminal(cmd: RunCommand, orig_termios: termios::Termios) -> (RawFd, P
let pid_secondary = match fork_pty_res.fork_result { let pid_secondary = match fork_pty_res.fork_result {
ForkResult::Parent { child } => child, ForkResult::Parent { child } => child,
ForkResult::Child => { ForkResult::Child => {
let child = Command::new(cmd.command) let child = unsafe {
.args(&cmd.args) Command::new(cmd.command)
.spawn() .args(&cmd.args)
.expect("failed to spawn"); .pre_exec(|| -> std::io::Result<()> {
// this is the "unsafe" part, for more details please see:
// https://doc.rust-lang.org/std/os/unix/process/trait.CommandExt.html#notes-and-safety
unistd::setpgid(Pid::from_raw(0), Pid::from_raw(0))
.expect("failed to create a new process group");
Ok(())
})
.spawn()
.expect("failed to spawn")
};
unistd::tcsetpgrp(0, Pid::from_raw(child.id() as i32))
.expect("faled to set child's forceground process group");
handle_command_exit(child); handle_command_exit(child);
::std::process::exit(0); ::std::process::exit(0);
} }