Warten Bash-Builtin brennt eine CPU zu 100 Prozent

15

Tritt mindestens auf GNU bash Version 4.3.42 x86_64 && GNU Bash - Version 4.3.11 x86_64

Ich benutze sleep & wait $!statt eines einfachen sleepum eine Unterbrechung sleepdurch ein Signal zu bekommen (als SIGUSR1 ). Aber es waitsieht so aus, als würde sich die Bash-Funktion auf seltsame Weise verhalten, wenn Sie Folgendes ausführen.

Terminal 1:

cat <(
   trap 'echo SIGUSR1' SIGUSR1;
   echo $BASHPID;
   while :;do
       sleep 1 &
       wait $!;
       echo test;
   done
   )&

Terminal 2:

kill -10 /the pid of the subshell, printed by the previous command/

Terminal 1:

^C (ctrl + C)

Dann bekomme ich die Subshell, die eine CPU zu 100 Prozent brennt.

Terminal 1:

pkill -P $(pgrep -P $$)

Haben Sie eine Vorstellung davon, warum dieses Verhalten auftritt?

NB : Es tritt kein Problem auf, wenn sich das cat <(/subshell/)nicht im Hintergrund befindet.


Ein anderer Weg, um dieses Verhalten zu erleben

Terminal 1:

(
   trap 'echo SIGUSR1' SIGUSR1;
   echo $BASHPID;
   while :;do
       sleep 1 &
       wait $!;
       echo test;
   done
)&

Terminal 2:

kill -10 /the pid of the subshell, printed by the previous command/

Terminal 1:

fg
^C (ctrl + C)

Dann holen Sie sich eine gefrorene Schale.


Ein dritter Weg, um dieses Verhalten zu erleben

Terminal 1:

(
   trap 'echo SIGUSR1' SIGUSR1;
   echo $BASHPID;
   while :;do
       sleep 1 &
       wait $!;
       echo test;
   done
)

Terminal 2:

kill -10 /the pid of the subshell, printed by the previous command/

Terminal 1:

^C (ctrl + C)

Dann holen Sie sich eine gefrorene Schale.

M89
quelle
Um dies zu debuggen, müssen Sie wahrscheinlich Bash aus Quellen erstellen und herausfinden, wo es eine Schleife gibt (brechen Sie es mit einem Debugger oder fügen Sie print-Anweisungen hinzu) und warum es eine Schleife gibt.
Kaz
1
Seltsam? Ich kann das hier nicht reproduzieren, ich verwende bash 4.3.42 (1) -release (x86_64-pc-linux-gnu). Debian 8. Kernel 4.6.1-1. Ich mache alle Tests, die Sie sagen, aber die CPU läuft immer noch normal ... Ich mache genau das, was Sie sagen, einschließlich der fg und dann STRG + C.
Luciano Andress Martini
Ich erinnere mich, dass ich gelesen habe, dass sich einige Dinge im Zusammenhang mit eingebauten Funktionen und Signalen in bash4.4 geändert haben. Vielleicht könnte dies hier betroffen sein.
Phk
Bash 4.4.20 behebt ein Spinloop-Problem wait, das dem sehr ähnlich sieht. Das traf mich in einer Schleife, die für immer Unterprozesse hervorbrachte. Ich habe Ihr Szenario jedoch auf 4.4.20 getestet und es war immer noch ein Problem. Interessanterweise , wenn ich einen Debugger an einer Version angebracht ich gebaut, konnte ich sehen , es wurde Umschlingung, aber es auch hatte die Wirkung , brechen aus ihm heraus, und die Schleife beginnen würde wieder ausgibt ‚test‘. Mit anderen Worten: Durch das Anhängen des Debuggers wurde das Schleifen beendet.
Halfgaar,

Antworten:

1

Beobachtungen

  • ctrl+cSendet SIGINTan den FG-Prozess in Terminal 1
  • Die Ausführung kill -2 <PID>in Terminal 2 entspricht daher der Ausführung ctrl+cin Terminal 1
  • Führen Sie einen der beiden oben genannten Punkte aus, bevor Sie die Ausführung kill -10 <PID>in Terminal 2 SIGINTkorrekt ausführen
  • Tun Sie dies nach der Ausführung kill -10 <PID>in Terminal 2 (Signal senden SIGUSR1) nicht SIGINTrichtig und führt zu einem problematischen Verhalten
  • Das Ersetzen kill -2 <PID>von Klemme 2 ( SIGINT) durch kill -15 <PID>( SIGTERM) oder kill -9 <PID>( SIGKILL) führt immer zu einer korrekten Signalbehandlung.
  • Die Ausführung kill -10 <PID>in Terminal 2 unterbricht die waiteingebaute Schleife, verlässt sie jedoch nicht, da sie testsofort gedruckt wird, nachdem das Signal abgefangen wurde SIGUSR1und die Schleife fortgesetzt wird.
  • Das Senden SIGINTunterbricht die Ausführungsschleife und friert die Shell ein oder sie unterbricht sie nie waitund bleibt warten / eingefroren.

Fazit

SIGINTwird nicht richtig erfasst und behandelt oder nach manuellem Überfüllen SIGUSR1oder anderen benutzerdefinierten Überfüllungen ignoriert . Das bedeutet, dass der Prozess noch vorhanden ist und deshalb die CPU aufgefressen / aufgeheizt oder die Shell eingefroren wird. Das Ausführen von kill -15 <PID>oder kill -9 <PID>von Terminal 2 beendet / beendet den Prozess und gibt Ihnen die Kontrolle über Terminal 1 zurück und entspannt Ihre CPU.

Warum dieses Problem auftritt, bleibt immer noch ein Rätsel, aber ich hoffe, jemand kann genau erklären, was sich wirklich hinter den Kulissen abspielt.

Neni
quelle