То, что вы наблюдаете, является ошибкой в этой версии 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-проверок, все происходит как положено.