Was Sie beobachten, ist ein Fehler in dieser Version von Bash.
kill -9 %1
tötet den Job sofort. Sie können das mit beobachten ps
. Sie können den Bash-Prozess verfolgen, um zu sehen, wann der kill
Systemaufruf aufgerufen wird, und den Unterprozess verfolgen, um zu sehen, wann er die Signale empfängt und verarbeitet. Interessanter ist, dass Sie sehen können, was mit dem Prozess passiert.
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$
In einem anderen Terminal:
% ps 3083
PID TTY STAT TIME COMMAND
3083 pts/4 Z 0:00 [sleep] <defunct>
Der Unterprozess ist ein Zombie . Es ist tot: Alles, was davon übrig bleibt, ist ein Eintrag in der Prozesstabelle (aber kein Speicher, Code, geöffnete Dateien usw.). Der Eintrag bleibt so lange bestehen, bis sein Elternteil es bemerkt und seinen Exit-Status durch Aufrufen des wait
Systemaufrufs oder eines seiner Geschwister abruft .
Eine interaktive Shell soll nach toten Kindern suchen und sie ernten, bevor eine Eingabeaufforderung gedruckt wird (sofern nicht anders konfiguriert). Diese Version von Bash funktioniert unter bestimmten Umständen nicht:
bash-4.3$ jobs -l
[1]+ 3083 Stopped sleep 9999
bash-4.3$ true
bash-4.3$ /bin/true
[1]+ Killed sleep 9999
Es ist zu erwarten, dass bash "Killed" meldet, sobald die Eingabeaufforderung nach dem kill
Befehl gedruckt wird. Dies ist jedoch nicht garantiert, da eine Racebedingung vorliegt. Signale werden asynchron kill
übermittelt : Der Systemaufruf kehrt zurück, sobald der Kernel herausgefunden hat, an welche Prozesse das Signal übermittelt werden soll, ohne darauf zu warten, dass es tatsächlich übermittelt wird. Es ist möglich, und es kommt in der Praxis vor, dass bash Zeit hat, den Status seines Unterprozesses zu überprüfen, festzustellen, dass er noch nicht tot ist ( wait4
keinen Kindstod meldet), und zu drucken, dass der Prozess immer noch gestoppt ist. Was falsch ist, ist, dass vor der nächsten Eingabeaufforderung das Signal übermittelt wurde ( ps
meldet, dass der Prozess beendet ist), Bash jedoch noch nicht aufgerufen wurdewait4
(Wir können das nicht nur sehen, weil der Job immer noch als "Gestoppt" gemeldet wird, sondern weil der Zombie immer noch in der Prozesstabelle vorhanden ist.) Tatsächlich erntet Bash den Zombie nur beim nächsten Aufruf wait4
, wenn er einen anderen externen Befehl ausführt.
Der Fehler tritt nur sporadisch auf und ich konnte ihn nicht reproduzieren, während Bash verfolgt wird (vermutlich, weil es sich um eine Race-Bedingung handelt, bei der Bash schnell reagieren muss). Wenn das Signal vor Bash-Checks geliefert wird, geschieht alles wie erwartet.