bash-builtin이 CPU를 100 % 구울 때까지 기다립니다.


16

에 적어도 발생 GNU bash는 버전 4.3.42 x86_64의 && GNU bash는 버전 4.3.11 x86_64의

신호 ( SIGUSR1 )에 의해 인터럽트 가능을 얻는 sleep & wait $!간단한 대신에 사용 합니다 . 그러나 bash 내장 기능은 다음을 실행할 때 이상한 방식으로 작동하는 것 같습니다.sleepsleepwait

터미널 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)

그런 다음 CPU를 100 % 레코딩하는 서브 쉘을 얻습니다.

터미널 1:

pkill -P $(pgrep -P $$)

이 동작이 발생하는 이유에 대해 알고 있습니까?

NB :가 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)

그런 다음 얼린 껍질을 얻으십시오.


이것을 디버깅하려면 아마도 소스에서 Bash를 빌드하고 루핑 위치 (디버거로 중단하거나 인쇄 문 추가)와 루핑 이유를 찾아야합니다.
Kaz

1
이상한? 나는 이것을 여기에서 재현 할 수 없다. 나는 bash 4.3.42 (1) -release (x86_64-pc-linux-gnu)를 사용하고있다. 데비안 8. 커널 4.6.1-1. 나는 당신이 말하는 모든 테스트를 수행하지만 CPU는 여전히 정상적으로 실행 중입니다 ... fg를 포함하여 CTRL + C를 포함하여 정확히 말하고 있습니다.
루치아노 안드레스 마티니

내장 및 신호와 관련된 일부 사항 bash이 4.4에서 변경되었음을 읽은 것을 기억 합니다. 여기에서 이것이 영향을받을 수 있습니다.
phk

Bash 4.4.20 에서 스핀 루프 문제 수정wait 은 이와 매우 유사한 . 나는 하위 프로세스를 영원히 생성 한 루프에서 그것에 맞았습니다. 그러나 4.4.20에서 시나리오를 테스트했지만 여전히 문제가되었습니다. 내가 내장 버전에 디버거를 연결하면 흥미롭게도, 나는 주위에 반복되었다 볼 수 있지만, 또한 그것의 파괴의 효과가 있고, 루프 다시 '시험'을 출력하기 시작합니다. 즉, 디버거를 연결하면 스핀 루핑이 중지됩니다.
Halfgaar

답변:


1

관찰

  • ctrl+cSIGINT터미널 1의 fg 프로세스로 전송
  • 따라서, 실행 kill -2 <PID>2 터미널에서 타격하는 것과 동일 ctrl+c터미널 1
  • 터미널 2에서 실행 하기 전에 위의 두 지점 중 하나를 올바르게 kill -10 <PID>처리 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가 갇히고 루프가 계속 된 후 즉시 printet 이기 때문에 루프를 떠나지 않습니다 .
  • 배상 SIGINT 는 실행 루프를 중단 wait하고 쉘을 정지 시키거나 중단 / 정지 상태를 유지합니다.

결론

SIGINT 움 직이고 올바르게 처리되지 않았거나 수동 트래핑 후 무시 됨 SIGUSR1 또는 다른 사용자 정의 트래핑 됩니다. 그것은 프로세스가 여전히 존재한다는 것을 의미하며, 이것이 CPU를 먹거나 가열하거나 쉘을 동결시키는 이유입니다. 터미널 2에서 실행 kill -15 <PID>하거나 kill -9 <PID>터미널 2에서 프로세스를 종료 / 종료하고 터미널 1에 대한 제어권을 다시주고 CPU를 완화시킵니다.

이 문제가 발생하는 이유는 여전히 미스터리이지만, 누군가 커튼 뒤에서 실제로 무슨 일이 일어나고 있는지 정확하게 설명 할 수 있기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.