Repository: zellij-org/zellij
File: zellij-server/src/os_input_output.rs (Rust)

Code before:
            let _ = child.kill();
            break 'handle_exit;
        }
    }
}

fn handle_fork_pty(
    fork_pty_res: ForkptyResult,
    cmd: RunCommand,
    parent_fd: RawFd,
    child_fd: RawFd,
) -> (RawFd, ChildId) {
    let pid_primary = fork_pty_res.master;
    let (pid_secondary, pid_shell) = match fork_pty_res.fork_result {
        ForkResult::Parent { child } => {
            let pid_shell = read_from_pipe(parent_fd, child_fd);
            (child, pid_shell)
        }
        ForkResult::Child => {
            let child = unsafe {
                let command = &mut Command::new(cmd.command);
                if let Some(current_dir) = cmd.cwd {
                    command.current_dir(current_dir);
                }
                command
                    .args(&cmd.args)
                    .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");
            write_to_pipe(child.id(), parent_fd, child_fd);
            handle_command_exit(child);
            ::std::process::exit(0);
        }
    };

    (
        pid_primary,
        ChildId {
            primary: pid_secondary,
            shell: pid_shell.map(|pid| Pid::from_raw(pid as i32)),
        },
    )

Review comment (suggestion):
I'm not sure if panics are safe in pre_exec. You can return some io error, and catch the error code (but not the text) in parent process as far as I remember.

Code after:
            // when I say whoa, I mean WHOA!
            let _ = child.kill();
            break 'handle_exit;
        }
    }
}

fn handle_openpty(
    open_pty_res: OpenptyResult,
    cmd: RunCommand,
    quit_cb: Box<dyn Fn(PaneId) + Send>,
) -> (RawFd, RawFd) {
    // primary side of pty and child fd
    let pid_primary = open_pty_res.master;
    let pid_secondary = open_pty_res.slave;

    let mut child = unsafe {
        let command = &mut Command::new(cmd.command);
        if let Some(current_dir) = cmd.cwd {
            command.current_dir(current_dir);
        }
        command
            .args(&cmd.args)
            .pre_exec(move || -> std::io::Result<()> {
                if libc::login_tty(pid_secondary) != 0 {
                    panic!("failed to set controlling terminal");
                }
                close_fds::close_open_fds(3, &[]);
                Ok(())
            })
            .spawn()
            .expect("failed to spawn")
    };

    let child_id = child.id();
    std::thread::spawn(move || {
        child.wait().unwrap();
        handle_command_exit(child);
        let _ = nix::unistd::close(pid_primary);
        let _ = nix::unistd::close(pid_secondary);
        quit_cb(PaneId::Terminal(pid_primary));
    });

    (pid_primary, child_id as RawFd)
}

/// Spawns a new terminal from the parent terminal with [`termios`](termios::Termios)
/// `orig_termios`.
///
fn handle_terminal(
    cmd: RunCommand,