Mari kita asumsikan kita memiliki daemon sepele yang ditulis dengan python:
def mainloop():
while True:
# 1. do
# 2. some
# 3. important
# 4. job
# 5. sleep
mainloop()
dan kami mengubahnya menggunakan start-stop-daemon
yang secara default mengirimkan sinyal SIGTERM
( TERM
) aktif --stop
.
Misalkan langkah saat ini dilakukan adalah #2
. Dan saat ini kami sedang mengirim TERM
sinyal.
Apa yang terjadi adalah bahwa eksekusi segera berakhir.
Saya telah menemukan bahwa saya dapat menangani acara sinyal menggunakan signal.signal(signal.SIGTERM, handler)
tetapi masalahnya adalah masih mengganggu eksekusi saat ini dan melewati kontrol handler
.
Jadi, pertanyaan saya adalah - apakah mungkin untuk tidak menghentikan eksekusi saat ini tetapi menangani TERM
sinyal di utas yang terpisah (?) Sehingga saya dapat mengatur shutdown_flag = True
sehingga mainloop()
memiliki kesempatan untuk berhenti dengan anggun?
sumber
signalfd
dan menutupi pengirimanSIGTERM
ke proses.Jawaban:
Solusi bersih untuk menggunakan berbasis kelas:
sumber
False
nilai ditetapkan hanya sekali, dan kemudian hanya bisa pergi dari False ke True sehingga beberapa akses tidak masalah.Pertama, saya tidak yakin Anda perlu utas kedua untuk mengatur
shutdown_flag
.Mengapa tidak mengaturnya langsung di handler SIGTERM?
Alternatifnya adalah dengan menaikkan pengecualian dari
SIGTERM
handler, yang akan diperbanyak ke atas tumpukan. Dengan asumsi Anda memiliki penanganan pengecualian yang tepat (misalnya denganwith
/contextmanager
dantry: ... finally:
blok) ini harus menjadi shutdown yang cukup anggun, mirip dengan jika Anda ke Ctrl+Cprogram Anda.Contoh program
signals-test.py
:Sekarang lihat Ctrl+Cperilaku:
Kali ini saya kirim
SIGTERM
setelah 4 iterasi dengankill $(ps aux | grep signals-test | awk '/python/ {print $2}')
:Kali ini saya mengaktifkan
SIGTERM
handler kustom saya dan mengirimkannyaSIGTERM
:sumber
Saya pikir Anda sudah dekat dengan solusi yang mungkin.
Jalankan
mainloop
di utas terpisah dan rentangkan dengan propertishutdown_flag
. Sinyal dapat ditangkap dengansignal.signal(signal.SIGTERM, handler)
di utas utama (bukan di utas terpisah). Penangan sinyal harus diaturshutdown_flag
ke True dan menunggu utas berakhirthread.join()
sumber
Berikut adalah contoh sederhana tanpa utas atau kelas.
sumber
Berdasarkan jawaban sebelumnya, saya telah membuat manajer konteks yang melindungi dari sigint dan sigterm.
sumber
Menemukan cara termudah untukku. Berikut ini contoh dengan garpu untuk kejelasan bahwa cara ini berguna untuk kontrol aliran.
sumber
Solusi paling sederhana yang saya temukan, mengambil inspirasi dari tanggapan di atas adalah
sumber