Вы все делаете неправильно.
Вы НЕ отправляете SIGTSTP дочернему процессу, tty отправляет SIGTSTP дочернему процессу ПРЯМО.
Попробуйте
$ stty -a
speed 38400 baud; rows 55; columns 204; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
Примечание:
susp = ^Z;
, который сообщает tty, как обращаться с "CTRL-Z", когда tty получает ^ Z, он отправляет сигнал SIGTSTP на весь процесс в текущей группе процессов переднего плана
Как обрабатывать группу процессов
Когда вы запускаете новый процесс в оболочке, перед execvX
поместите новый процесс в новую группу процессов, затем вызовите tcsetpgrp
, чтобы установитьновый план группы процессов.Таким образом, любой будущий сигнал отправит дочернему процессу напрямую.если ребенок разветвляет новый процесс, он будет в той же группе процессов;поэтому при нажатии ^ Z вся группа процессов будет приостановлена.
pid = fork()
if (pid) {
// parent
setpgid(pid, pid); // put child into a new process group
int status;
wait(pid, &status, 0);
} else {
// child
pid = getpid();
setpgid(pid, pid);
if (isatty(0)) tcsetpgrp(0, pid);
if (isatty(1)) tcsetpgrp(1, pid);
if (isatty(2)) tcsetpgrp(2, pid);
execvX ...
}
Как только поступит какой-либо сигнал от tty, вызывающий остановку / термин / выход дочерних процессов, ваша оболочка вернется из wait
, проверьте состояние, чтобы узнатьчто случилось с ребенком.
Предотвращение остановки вашей оболочки
Ваша оболочка должна маскировать сигнал SIGTSTP, потому что оболочка не приостанавливается.Вы делаете это в начале, когда вы запускаете оболочку.но не забывайте, что fork получит сигма-маску, поэтому вам нужно включить SIGTSTP после fork в дочернем процессе.