Происходит по крайней мере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 и расслабляет ваш ЦП.
Почему возникает эта проблема, до сих пор остается загадкой, но я надеюсь, что кто-нибудь сможет объяснить, что именно происходит за кулисами.