Mengapa loop sementara berhenti setelah ditangguhkan?

10

Mengapa menggunakan bash dan menangguhkan loop sementara, loop berhenti setelah dilanjutkan? Contoh singkat di bawah ini.

$ while true; do echo .; sleep 1; done
.
.
^Z
[1]+  Stopped                 sleep 1
$ fg
sleep 1
$

Saya akrab dengan sinyal, dan saya menduga ini mungkin merupakan perilaku alami bash di sini, tetapi saya ingin lebih memahami mengapa berperilaku dengan cara tertentu.

bkzland
sumber
karena harus menangani interupsi dan harus secara akurat mencerminkan bahwa $?pada pengembalian, dan truetidak demikian halnya true. mungkin. kupikir.
mikeserv
1
Saya harap komentar ini tidak ditandai, tetapi saya akan menjawab pertanyaan Anda dengan pertanyaan lain, Unix koan-style: "Mengapa seorang siswa berhenti berkelahi di taman bermain setelah dia diskors?" Jawabannya adalah, karena dia tidak lagi di taman bermain di mana dia memiliki kemampuan untuk memulai perkelahian. Dengan demikian, perilaku yang dipermasalahkan telah dihentikan.
rubynorails
Anda menghentikan perintah, loop rusak. Kemudian Anda melanjutkan perintah sleep 1 tunggal, bukan loop.
123
1
Relevan
123

Jawaban:

10

Ini terlihat seperti bug di beberapa shell, berfungsi seperti yang diharapkan dengan ksh93 dan zsh .

Latar Belakang:

Kebanyakan shell tampaknya menjalankan loop sementara di dalam shell utama dan

Bourne Shell menangguhkan seluruh shell jika Anda mengetikkan ^ Z dengan shell non-login

bash hanya menangguhkan sleepdan kemudian meninggalkan loop sementara demi mencetak prompt shell baru

dash membuat perintah ini tidak dapat ditangguhkan

Dengan ksh93 , semuanya bekerja sangat berbeda:

ksh93 melakukan hal yang sama, ketika perintah dimulai pertama kali, tetapi seperti sleepbuitin di ksh93, ksh93 memiliki handler yang menyebabkan loop sementara untuk memotong shell utama dan kemudian menunda pada saat Anda mengetikkan ^ Z.

Jika Anda dalam tipe ksh93 nanti fg, anak bercabang yang masih menjalankan loop dilanjutkan.

Anda melihat perbedaan utama ketika membandingkan pesan kontrol pekerjaan dari bash dan ksh93:

laporan bash :

[1]+ Stopped sleep 1

tapi ksh93 melaporkan:

^Z[1] + Stopped while true; do echo .; sleep 1; done

zsh berperilaku mirip dengan ksh93

Dengan kedua shell, Anda memiliki satu proses (shell utama) selama Anda tidak mengetikkan ^ Z, dan dua proses shell setelah Anda mengetikkan ^ Z.

schily
sumber
tidak dashbenar - benar berakhir menangani sinyal ketika loop berakhir? dalam [d]?ashkode sumber ada semua makro untuk INTON dan INTOFF tersebar di seluruh, dan biasanya sinyal yang diterima saat dalam keadaan INTOFF benar-benar ditangani pada (atau sekitar) INTON . Lagi pula, saya hanya ingin tahu karena saya pikir Anda tahu lebih baik - itu adalah jawaban yang bagus. Terima kasih.
mikeserv
Saya jarang menggunakan tanda hubung dan saya baru-baru ini mengambil dan mengompilasinya untuk perbandingan kinerja dengan bash, ksh93 dan Bourne Shell saya. Saat melakukan tes ini, saya menemukan bahwa dasbor terutama tampaknya cepat karena tidak termasuk dukungan untuk karakter multi-byte. Satu sleep 100dapat ditangguhkan dan dilanjutkan dash, sehingga tampaknya dashmengetahui tentang masalah dalam perintah ini dan secara selektif menonaktifkan kontrol pekerjaan.
schily
jadi, dalam pengujian Anda, Anda dapat menyamai dashkinerja di shell lain dengan menjatuhkan pemrosesan multibyte? dan ya, dashmemang mendukung kontrol pekerjaan, tetapi standar mengatakan shell interaktif harus mengabaikan TSTP, dan menjalankan loop sementara di shell saat ini di terminal interaktif tidak kurang dari shell interaktif daripada yang lain.
mikeserv
Saya tidak menguji ini persis, tapi saya bisa melihat bahwa sementara dash mengkonsumsi lebih banyak waktu sistem CPU daripada ksh93 atau Bourne Shell (terutama karena ia mengeluarkan lebih banyak fork () panggilan), ia menggunakan lebih sedikit waktu CPU pengguna dan ini menghasilkan total yang serupa Waktu CPU dibandingkan dengan versi saya dari Bourne Shell. Dari mencoba mengurangi waktu CPU pengguna di Bourne Shell, saya tahu bahwa sebagian besar waktu ini dihabiskan dalam konversi multibyte.
schily
4

Saya menulis salah satu penulis Bash tentang masalah ini, dan inilah jawabannya:

Ini sebenarnya bukan bug, tetapi tentu saja peringatan.

Idenya di sini adalah bahwa Anda menunda proses, yang merupakan unit granularity berbeda dari perintah shell. Ketika suatu proses ditangguhkan, ia kembali ke shell (dengan status non-nol, yang memiliki konsekuensi ketika Anda, katakanlah, hentikan proses yang merupakan tes loop), yang memiliki pilihan: ia dapat keluar atau melanjutkan loop , meninggalkan proses yang terhenti. Bash memilih - dan selalu memilih - untuk keluar dari lingkaran ketika pekerjaan dihentikan. Melanjutkan pengulangan jarang seperti yang Anda inginkan.

Beberapa shell lain melakukan hal-hal seperti garpu salinan shell ketika suatu proses ditangguhkan karena SIGTSTP, dan menghentikan proses itu. Bash belum pernah melakukan itu - tampaknya lebih rumit daripada jaminan manfaat - tetapi jika seseorang ingin mengirimkan kode itu sebagai tambalan, saya akan melihat memasukkan perubahan.

Jadi, jika ada yang ingin mengirimkan tambalan, gunakan alamat email yang ada di halaman manual.

sebagainya
sumber