รอ bash-builtin เบิร์น CPU ที่ 100 เปอร์เซ็นต์


16

เกิดขึ้นอย่างน้อยในGNU bash รุ่น 4.3.42 x86_64 && GNU bash รุ่น 4.3.11 x86_64

ฉันใช้sleep & wait $!แทนวิธีง่าย ๆsleepในการทำให้sleepสัญญาณขัดจังหวะ(เหมือนSIGUSR1 ) แต่ดูเหมือนว่าwaitbash-builtin จะทำงานในลักษณะที่แปลกเมื่อคุณเรียกใช้สิ่งต่อไปนี้

อาคาร 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)

จากนั้นฉันจะได้รับ subshell ที่เผาไหม้ CPU ที่ 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)

จากนั้นรับเปลือกแช่แข็ง


ในการแก้ไขปัญหานี้คุณอาจต้องสร้าง Bash จากแหล่งที่มาและหาตำแหน่งที่มันวนซ้ำ
Kaz

1
แปลก? ฉันทำซ้ำไม่ได้ที่นี่ฉันใช้ bash 4.3.42 (1) - ปล่อย (x86_64-pc-linux-gnu) เดเบียน 8. เคอร์เนล 4.6.1-1 ฉันทำการทดสอบทั้งหมดที่คุณพูด แต่ CPU ยังคงทำงานตามปกติ ... ฉันกำลังทำเหมือนกับที่คุณพูดรวมถึง fg แล้ว CTRL + C
Luciano Andress Martini

ฉันจำได้ว่าอ่านบางสิ่งเกี่ยวกับบิวด์อินและสัญญาณที่เปลี่ยนไปในbash4.4 บางทีนี่อาจได้รับผลกระทบ
phk

Bash 4.4.20แก้ไขปัญหา spinloop waitที่มีลักษณะคล้ายกันมาก ฉันถูกโจมตีด้วยการวนซ้ำที่เกิดกระบวนการย่อยตลอดไป อย่างไรก็ตามฉันทดสอบสถานการณ์ของคุณใน 4.4.20 และยังคงมีปัญหาอยู่ ที่น่าสนใจเมื่อฉันแนบดีบักเกอร์ในเวอร์ชันที่ฉันสร้างขึ้นฉันเห็นว่ามันวนลูปไปรอบ ๆ แต่มันก็มีผลกระทบจากการแตกออกและลูปจะเริ่มส่ง 'ทดสอบ' อีกครั้ง กล่าวอีกนัยหนึ่ง: การแนบดีบักเกอร์ทำให้หยุดการหมุนได้
Halfgaar

คำตอบ:


1

ข้อสังเกต

  • ctrl+cส่งSIGINTไปยังกระบวนการ fg ในเทอร์มินัล 1
  • ดังนั้นการดำเนินการkill -2 <PID>ในเทอร์มินัล 2 จึงเหมือนกับการกดปุ่มctrl+cในเทอร์มินัล 1
  • ทำหนึ่งในสองจุดข้างต้นก่อนที่จะดำเนินการkill -10 <PID>ใน Terminal 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 และช่วยให้ CPU ของคุณผ่อนคลาย

ทำไมปัญหานี้เกิดขึ้นยังคงเป็นปริศนา แต่ฉันหวังว่าใครบางคนสามารถอธิบายได้อย่างชัดเจนว่าเกิดอะไรขึ้นหลังม่าน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.