czekaj wbudowane bash pali procesor na 100 procentach

16

Występuje przynajmniej w wersji GNU bash 4.3.42 x86_64 i & GNU bash wersja 4.3.11 x86_64

Używam sleep & wait $!zamiast prostego sleepdo uzyskania przerwania sleepprzez sygnał (jako SIGUSR1 ). Ale wygląda na to, że waitwbudowane bash zachowuje się w dziwny sposób, gdy uruchomisz następujące.

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)

Następnie otrzymuję podpowłokę, która spala procesor w 100 procentach.

Terminal 1:

pkill -P $(pgrep -P $$)

Czy masz pojęcie o tym, dlaczego tak się dzieje?

Uwaga : nie występuje problem, gdy cat <(/subshell/)nie ma go w tle.


Kolejny sposób, aby doświadczyć tego zachowania

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)

Następnie weź zamrożoną skorupę.


Trzeci sposób na doświadczenie tego zachowania

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)

Następnie weź zamrożoną skorupę.

M89
źródło
Aby to debugować, prawdopodobnie musisz zbudować Bash ze źródeł i dowiedzieć się, gdzie się zapętla (przerwij go za pomocą debuggera lub dodaj instrukcje print) i dlaczego zapętla się.
Kaz
1
Dziwne? Nie mogę tego odtworzyć tutaj, używam bash 4.3.42 (1) -release (x86_64-pc-linux-gnu). Debian 8. Jądro 4.6.1-1. Wykonuję wszystkie testy, które mówisz, ale procesor nadal działa normalnie ... Robię dokładnie tak, jak mówisz, w tym fg, a następnie CTRL + C.
Luciano Andress Martini
Pamiętam, że czytałem, że niektóre rzeczy związane z wbudowanymi funkcjami i sygnałami zmieniły się w bash4.4, może to tutaj mieć wpływ.
phk,
Bash 4.4.20 naprawia problem spinloop, waitktóry wygląda bardzo podobnie do tego. Uderzyło mnie to w pętli, która odrodziła podprocesy na zawsze. Jednak przetestowałem twój scenariusz w dniu 4.4.20 i nadal był problem. Co ciekawe, kiedy dołączyłem debugger do zbudowanej przeze mnie wersji, widziałem, że się zapętla, ale miał również efekt wyrwania się z niego, a pętla znów zaczyna „testować”. Innymi słowy: dołączenie debuggera sprawiło, że przestał on spinloopować.
Halfgaar,

Odpowiedzi:

1

Spostrzeżenia

  • ctrl+cwysyła SIGINTdo procesu fg w Terminalu 1
  • stąd wykonywanie kill -2 <PID>w Terminalu 2 jest tym samym, co trafienie ctrl+cw Terminalu 1
  • wykonanie jednego z dwóch powyższych punktów przed prawidłowym wykonaniem kill -10 <PID>w uchwytach terminala 2SIGINT
  • robienie tego po uruchomieniu kill -10 <PID>w Terminalu 2 (wysyłanie sygnału SIGUSR1) nie obsługuje SIGINTpoprawnie i prowadzi do problematycznego zachowania
  • Zamiana kill -2 <PID>w Terminalu 2 ( SIGINT) na kill -15 <PID>( SIGTERM) lub kill -9 <PID>( SIGKILL) zawsze prowadzi do poprawnej obsługi sygnału.
  • wykonanie kill -10 <PID>w Terminalu 2 przerywa waitwbudowane, ale nie opuszcza pętli, ponieważ testjest natychmiast drukowane po SIGUSR1uwięzieniu sygnału i kontynuowaniu pętli.
  • Wysyłanie SIGINTprzerywa wykonywanie pętli i zamraża powłokę lub nigdy nie przerywa waiti pozostaje w oczekiwaniu / zamrożone.

Wniosek

SIGINTnie jest traktowany i obsługiwany poprawnie lub jest ignorowany po ręcznym pułapkowaniu SIGUSR1lub innym pułapkom zdefiniowanym przez użytkownika. Oznacza to, że proces nadal istnieje i dlatego zjada / nagrzewa procesor lub zamraża powłokę. Wykonywanie kill -15 <PID>lub kill -9 <PID>z Terminalu 2 kończy / zabija proces i daje ci kontrolę nad Terminalem 1 i odpręża procesor.

Dlaczego ten problem występuje, nadal pozostaje tajemnicą, ale mam nadzieję, że ktoś może dokładnie wyjaśnić, co naprawdę dzieje się za zasłonami.

Neni
źródło