Terjadi setidaknya pada GNB bash versi 4.3.42 x86_64 && GNU bash versi 4.3.11 x86_64
Saya menggunakan sleep & wait $!
bukannya sederhana sleep
untuk mendapatkan interupsi sleep
oleh sinyal (seperti SIGUSR1 ). Tetapi tampaknya wait
bash-builtin berperilaku aneh ketika Anda menjalankan yang berikut.
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)
Lalu, saya mendapatkan subkulit yang membakar CPU pada 100 persen.
Terminal 1:
pkill -P $(pgrep -P $$)
Apakah Anda tahu mengapa perilaku ini terjadi?
NB : tidak ada masalah terjadi ketika cat <(/subshell/)
tidak ada di latar belakang.
Cara lain untuk mengalami perilaku ini
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)
Lalu, dapatkan cangkang beku.
Cara ketiga untuk mengalami perilaku ini
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)
Lalu, dapatkan cangkang beku.
bash
4.4, mungkin ini di sini bisa terpengaruh.wait
yang terlihat sangat mirip dengan ini. Saya terpukul oleh hal itu dalam satu lingkaran yang menelurkan sub-proses selamanya. Namun, saya menguji skenario Anda pada 4.4.20 dan itu masih menjadi masalah. Menariknya, ketika saya melampirkan debugger pada versi yang saya buat, saya bisa melihatnya sedang berputar, tetapi juga memiliki efek memutarnya, dan loop akan mulai menghasilkan 'tes' lagi. Dengan kata lain: melampirkan debugger membuatnya berhenti spinlooping.Jawaban:
Pengamatan
ctrl+c
mengirimSIGINT
ke proses fg di Terminal 1kill -2 <PID>
di Terminal 2 sama dengan memukulctrl+c
di Terminal 1kill -10 <PID>
di Terminal 2 menanganiSIGINT
dengan benarkill -10 <PID>
di Terminal 2 (mengirim sinyalSIGUSR1
) tidak menanganiSIGINT
dengan benar dan mengarah ke perilaku bermasalahkill -2 <PID>
Terminal 2 (SIGINT
) dengankill -15 <PID>
(SIGTERM
) ataukill -9 <PID>
(SIGKILL
) selalu mengarah ke penanganan sinyal yang benar.kill -10 <PID>
di Terminal 2 menggangguwait
builtin tetapi tidak meninggalkan loop karenatest
segera dicetak setelah sinyalSIGUSR1
terperangkap dan loop berlanjut.SIGINT
keluar dari loop eksekusi dan membekukan shell atau tidak pernah menggangguwait
dan tetap menunggu / beku.Kesimpulan
SIGINT
tidak ditangkap dan ditangani dengan benar atau diabaikan setelah menjebak secara manualSIGUSR1
atau mungkin penjebak lain yang ditentukan pengguna. Itu berarti bahwa prosesnya masih ada dan itulah mengapa ia memakan / memanaskan CPU atau membekukan shell. Menjalankankill -15 <PID>
ataukill -9 <PID>
dari Terminal 2 mengakhiri / membunuh proses dan memberi Anda kembali kendali atas Terminal 1 dan melemaskan CPU Anda.Mengapa masalah ini terjadi, masih tetap menjadi misteri, tetapi saya harap seseorang dapat menjelaskan dengan tepat apa yang sebenarnya terjadi di balik tirai.
sumber