1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//! Child-side controlling-terminal setup, run after fork and before exec.
use io;
use Command as TokioCommand;
/// Install the `pre_exec` hook that makes the slave PTY the child's controlling
/// terminal.
///
/// By the time the hook runs, the spawn machinery has already dup'd the slave
/// onto the child's fds 0/1/2. The hook then:
/// 1. `setsid()` — start a new session so the child is a session leader with no
/// controlling terminal (a prerequisite for acquiring one), which also makes
/// it a process-group leader whose group id equals its pid.
/// 2. `ioctl(0, TIOCSCTTY)` — acquire the slave (now fd 0) as the controlling
/// terminal, so the child and its descendants see a real interactive tty.
///
/// Because `setsid` establishes the process group, this hook intentionally
/// replaces the plain `setpgid` isolation used for pipe-backed modes; the
/// resulting group id still equals the child pid. `setsid` is mandatory for
/// acquiring a controlling terminal, so PTY mode always starts a new session
/// and process group: it requires [`SignalPolicy::create_process_group`] to be
/// enabled and rejects the run otherwise (see `run_pty_mode`). Given that, the
/// group layout matches the pipe-backed path, so group-targeted termination
/// under [`SignalPolicy`] behaves identically to the non-PTY modes.
///
/// [`SignalPolicy`]: crate::SignalPolicy
/// [`SignalPolicy::create_process_group`]: crate::SignalPolicy::create_process_group
pub