espere, o bash-builtin queima uma CPU em 100 por cento

espere, o bash-builtin queima uma CPU em 100 por cento

Ocorre pelo menos emGNU bash versão 4.3.42 x86_64&&GNU bash versão 4.3.11 x86_64

Eu uso sleep & wait $!em vez de um simples sleeppara obter um sleepsinal interrompível (comoSIGUSR1). Mas parece que o waitbash-builtin se comporta de maneira estranha quando você executa o seguinte.

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)

Então, recebo o subshell que queima a CPU a 100 por cento.

Terminal 1:

pkill -P $(pgrep -P $$)

Você tem alguma ideia de por que esse comportamento ocorre?

Observação: nenhum problema ocorre quando cat <(/subshell/)não está em segundo plano.


Outra maneira de experimentar esse comportamento

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)

Então, pegue uma casca congelada.


Uma terceira maneira de vivenciar esse comportamento

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)

Então, pegue uma casca congelada.

Responder1

Observações

  • ctrl+cenvia SIGINTpara o processo fg no Terminal 1
  • portanto, executar kill -2 <PID>no Terminal 2 é o mesmo que clicar ctrl+cno Terminal 1
  • fazendo um dos dois pontos acimaantesexecutando kill -10 <PID>no Terminal 2 manipula SIGINTcorretamente
  • Fazendodepoisa execução kill -10 <PID>no Terminal 2 (envio de sinal SIGUSR1) não funciona SIGINTcorretamente e leva ao comportamento problemático
  • Substituir kill -2 <PID>no Terminal 2 ( SIGINT) por kill -15 <PID>( SIGTERM) ou kill -9 <PID>( SIGKILL) leva sempre ao correto tratamento do sinal.
  • a execução kill -10 <PID>no Terminal 2 interrompe o waitbuilt-in, mas não sai do loop, pois testé imediatamente impresso após o sinal SIGUSR1ser capturado e o loop continuar.
  • O envio SIGINTsai do loop de execução e congela o shell ou nunca interrompe waite fica esperando/congelado.

Conclusão

SIGINTnão é capturado e tratado corretamente ou é ignorado após a captura manual SIGUSR1ou talvez qualquer outra captura definida pelo usuário. Isso significa que o processo ainda existe e é por isso que ele consome/aquece a CPU ou congela o shell. A execução kill -15 <PID>ou kill -9 <PID>a partir do Terminal 2 encerra/elimina o processo e devolve o controle sobre o Terminal 1 e relaxa sua CPU.

Por que esse problema ocorre ainda permanece um mistério, mas espero que alguém possa explicar exatamente o que realmente está acontecendo nos bastidores.

informação relacionada