(Повторная публикация в Unix согласно предложению в /programming/13718394/what-should-interactive-shells-do-in-orphaned-process-groups )
Короткий вопрос: что должна делать оболочка, если она находится в потерянной группе процессов, которой не принадлежит tty? Но я рекомендую прочитать длинный вопрос, потому что это забавно.
Вот забавный и увлекательный способ превратить ваш ноутбук в портативный обогреватель, используя вашу любимую оболочку (если вы не один из тех чудаков tcsh):
#include <unistd.h>
int main(void) {
if (fork() == 0) {
execl("/bin/bash", "/bin/bash", NULL);
}
return 0;
}
Это заставляет bash привязать процессор на 100%. zsh и fish делают то же самое, в то время как ksh и tcsh бормочут что-то о контроле за работой, а затем опрокидывают, что немного лучше, но не намного. О, и это преступник, не зависящий от платформы: затронуты как OS X, так и Linux.
Мой (потенциально неправильно) объяснение заключается в следующем: ребенок оболочка определяет , что она не на переднем плане: tcgetpgrp(0) != getpgrp()
. Поэтому он пытается остановить себя killpg(getpgrp(), SIGTTIN)
. Но его группа процессов является осиротевшей, потому что ее родитель (программа C) был лидером и умер, а SIGTTIN
отправленный в потерянную группу процессов просто отбрасывается (иначе ничто не сможет запустить его снова). Поэтому дочерняя оболочка не останавливается, но все еще находится в фоновом режиме, поэтому она делает все это снова, прямо сейчас. Промыть и повторить.
У меня вопрос, как оболочка командной строки может обнаружить этот сценарий и что для него нужно сделать? У меня есть два решения, ни одно из которых не является идеальным:
- Попробуйте сообщить о процессе, чей pid совпадает с идентификатором нашей группы. Если это не помогает
ESRCH
, значит, мы, вероятно, осиротели. - Попробуйте неблокирующее чтение одного байта из
/dev/tty
. Если это не помогаетEIO
, значит, мы, вероятно, осиротели.
(Наша проблема отслеживания это https://github.com/fish-shell/fish-shell/issues/422 )
Спасибо за ваши мысли!