Supongamos que tenemos un demonio tan trivial escrito en python:
def mainloop():
while True:
# 1. do
# 2. some
# 3. important
# 4. job
# 5. sleep
mainloop()
y lo damonizamos usando start-stop-daemon
que por defecto envía señal SIGTERM
( TERM
) --stop
.
Supongamos que el paso actual realizado es #2
. Y en este mismo momento estamos enviando TERM
señal.
Lo que sucede es que la ejecución termina de inmediato.
Descubrí que puedo manejar el evento de señal usando, signal.signal(signal.SIGTERM, handler)
pero la cuestión es que todavía interrumpe la ejecución actual y pasa el control a handler
.
Entonces, mi pregunta es: ¿es posible no interrumpir la ejecución actual sino manejar la TERM
señal en un hilo separado (?) Para poder configurarlo shutdown_flag = True
y mainloop()
tener la oportunidad de detenerlo con gracia?
python
daemon
sigterm
start-stop-daemon
zerkms
fuente
fuente
signalfd
y enmascarar la entrega delSIGTERM
proceso.Respuestas:
Una solución limpia para usar basada en la clase:
fuente
False
valor se establece solo una vez, y luego solo puede pasar de False a True para que el acceso múltiple no sea un problema.Primero, no estoy seguro de que necesites un segundo hilo para configurar el
shutdown_flag
.¿Por qué no configurarlo directamente en el controlador SIGTERM?
Una alternativa es generar una excepción desde el
SIGTERM
controlador, que se propagará por la pila. Suponiendo que tiene el manejo adecuado de excepciones (por ejemplo, conwith
/contextmanager
ytry: ... finally:
bloques), este debería ser un cierre bastante elegante, similar a si estuviera en Ctrl+Csu programa.Programa de ejemplo
signals-test.py
:Ahora vea el Ctrl+Ccomportamiento:
Esta vez lo envío
SIGTERM
después de 4 iteraciones conkill $(ps aux | grep signals-test | awk '/python/ {print $2}')
:Esta vez habilito mi
SIGTERM
controlador personalizado y lo envíoSIGTERM
:fuente
Creo que estás cerca de una posible solución.
Ejecute
mainloop
en un hilo separado y extiéndalo con la propiedadshutdown_flag
. La señal puede capturarsesignal.signal(signal.SIGTERM, handler)
en el hilo principal (no en un hilo separado). El controlador de señal debe establecerseshutdown_flag
en True y esperar a que el hilo termine conthread.join()
fuente
Aquí hay un ejemplo simple sin hilos o clases.
fuente
Basado en las respuestas anteriores, he creado un administrador de contexto que protege de sigint y sigterm.
fuente
Encontré la manera más fácil para mí. Aquí un ejemplo con fork para aclarar que de esta manera es útil para el control de flujo.
fuente
La solución más simple que he encontrado, inspirándome en las respuestas anteriores es
fuente