подождите, bash-builtin загрузит процессор на 100 процентов

подождите, bash-builtin загрузит процессор на 100 процентов

Происходит по крайней мереGNU bash версии 4.3.42 x86_64&&GNU bash версии 4.3.11 x86_64

Я использую sleep & wait $!вместо простого sleepдля получения прерываемого sleepсигнала (какSIGUSR1). Но, похоже, waitвстроенная функция bash ведет себя странно, когда вы запускаете следующее.

Терминал 1:

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

Терминал 2:

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

Терминал 1:

^C (ctrl + C)

Затем я получаю подоболочку, которая загружает процессор на 100 процентов.

Терминал 1:

pkill -P $(pgrep -P $$)

Есть ли у вас какие-либо идеи о том, почему происходит такое поведение?

Примечание.: никаких проблем не возникает, когда cat <(/subshell/)не находится в фоновом режиме.


Другой способ испытать это поведение

Терминал 1:

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

Терминал 2:

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

Терминал 1:

fg
^C (ctrl + C)

Затем возьмите замороженную ракушку.


Третий способ испытать это поведение

Терминал 1:

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

Терминал 2:

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

Терминал 1:

^C (ctrl + C)

Затем возьмите замороженную ракушку.

решение1

Наблюдения

  • ctrl+cотправляет SIGINTв fg-процесс в Терминале 1
  • следовательно, выполнение kill -2 <PID>в Терминале 2 равносильно удару ctrl+cв Терминале 1
  • выполнение одного из двух вышеуказанных пунктовдовыполнение kill -10 <PID>в Терминале 2 обрабатывается SIGINTправильно
  • Делать этопослевыполнение kill -10 <PID>в Терминале 2 (отправка сигнала SIGUSR1) обрабатывается SIGINTнеправильно и приводит к проблемному поведению
  • Замена kill -2 <PID>в Терминале 2 ( SIGINT) на kill -15 <PID>( SIGTERM) или kill -9 <PID>( SIGKILL) всегда приводит к правильной обработке сигнала.
  • выполнение kill -10 <PID>в Терминале 2 прерывает waitвстроенную функцию, но не выходит из цикла, поскольку testпечатается сразу после перехвата сигнала, SIGUSR1и цикл продолжается.
  • Отправка SIGINTпрерывает цикл выполнения и замораживает оболочку или она никогда не прерывается waitи остается в состоянии ожидания/замороженной.

Заключение

SIGINTне перехватывается и не обрабатывается правильно или игнорируется после ручного прерывания SIGUSR1или, возможно, любого другого определенного пользователем прерывания. Это означает, что процесс все еще существует, и поэтому он потребляет/нагревает ЦП или замораживает оболочку. Выполнение kill -15 <PID>или kill -9 <PID>из Терминала 2 завершает/убивает процесс и возвращает вам контроль над Терминалом 1 и расслабляет ваш ЦП.

Почему возникает эта проблема, до сих пор остается загадкой, но я надеюсь, что кто-нибудь сможет объяснить, что именно происходит за кулисами.

Связанный контент