То, что вы наблюдаете, является ошибкой в этой версии bash.
kill -9 %1
убивает работу немедленно. Вы можете наблюдать это с ps
. Вы можете отслеживать процесс bash, чтобы видеть, когда kill
вызывается системный вызов, и отслеживать подпроцесс, чтобы видеть, когда он получает и обрабатывает сигналы. Более того, вы можете пойти и посмотреть, что происходит с процессом.
bash-4.3$ sleep 9999
^Z
[1]+ Stopped sleep 9999
bash-4.3$ kill -9 %1
[1]+ Stopped sleep 9999
bash-4.3$ jobs
[1]+ Stopped sleep 9999
bash-4.3$ jobs -l
[1]+ 3083 Stopped sleep 9999
bash-4.3$
В другом терминале:
% ps 3083
PID TTY STAT TIME COMMAND
3083 pts/4 Z 0:00 [sleep] <defunct>
Подпроцесс - это зомби . Он мертв: от него остается только запись в таблице процессов (но без памяти, кода, открытых файлов и т. Д.). Запись остается до тех пор, пока ее родитель не заметит и не получит статус выхода, вызвав wait
системный вызов или одного из своих братьев и сестер .
Предполагается, что интерактивная оболочка проверяет наличие мертвых детей и собирает их перед печатью приглашения (если не указано иное). Эта версия bash не может сделать это при некоторых обстоятельствах:
bash-4.3$ jobs -l
[1]+ 3083 Stopped sleep 9999
bash-4.3$ true
bash-4.3$ /bin/true
[1]+ Killed sleep 9999
Вы можете ожидать, что bash сообщит «Killed», как только напечатает приглашение после kill
команды, но это не гарантировано, потому что есть условие гонки. Сигналы доставляются асинхронно: kill
системный вызов возвращается, как только ядро выяснило, в какой процесс (ы) доставить сигнал, не дожидаясь его фактической доставки. Возможно, и на практике это происходит, когда bash успевает проверить состояние своего подпроцесса, обнаружить, что он все еще не мертв ( wait4
не сообщает о смерти ребенка), и напечатать, что процесс все еще остановлен. Что неправильно, так это то, что перед следующим приглашением сигнал был доставлен ( ps
сообщает, что процесс мертв), но bash все еще не вызвалwait4
(мы видим это не только потому, что он по-прежнему сообщает о задании как «Остановлено», но и потому, что зомби все еще присутствует в таблице процессов). На самом деле, bash получает зомби только в следующий раз wait4
, когда ему нужно позвонить , когда он запускает какую-то другую внешнюю команду.
Ошибка периодически, и я не мог воспроизвести ее, пока отслеживается bash (возможно, потому что это состояние гонки, где bash должен реагировать быстро). Если сигнал доставляется до bash-проверок, все происходит как положено.