Python: cómo evitar que los subprocesos reciban CTRL-C/Control-C/SIGINT
subprocess signals (4)
Actualmente estoy trabajando en un contenedor para un servidor dedicado que se ejecuta en el shell. El contenedor genera el proceso del servidor a través del subproceso y observa y reacciona a su salida.
Al servidor dedicado se le debe dar explícitamente un comando para cerrarlo correctamente. Por lo tanto, CTRL-C no debe alcanzar el proceso del servidor.
Si capturo la excepción KeyboardInterrupt o sobreescribo el SIGINT-handler en python, el proceso del servidor aún recibe el CTRL-C y se detiene inmediatamente.
Entonces mi pregunta es: ¿Cómo evitar que los subprocesos reciban CTRL-C / Control-C / SIGINT?
Alguien en el #python IRC-Channel (Freenode) me ayudó señalando el parámetro preexec_fn del subproceso.Popen (...) :
Si preexec_fn se establece en un objeto invocable, se llamará a este objeto en el proceso hijo justo antes de que se ejecute el elemento secundario. (Solo Unix)
Por lo tanto, el siguiente código resuelve el problema (solo UNIX):
import subprocess
import signal
def preexec_function():
# Ignore the SIGINT signal by setting the handler to the standard
# signal handler SIG_IGN.
signal.signal(signal.SIGINT, signal.SIG_IGN)
my_process = subprocess.Popen(
["my_executable"],
preexec_fn = preexec_function
)
Nota: De hecho, no se impide que la señal llegue al subproceso. En su lugar, el preexec_fn anterior sobrescribe el controlador predeterminado de la señal para que se ignore la señal. Por lo tanto, esta solución puede no funcionar si el subproceso sobrescribe el controlador SIGINT nuevamente.
Otra nota: esta solución funciona para todo tipo de subprocesos, es decir, no está restringida a subprocesos escritos en Python también. Por ejemplo, el servidor dedicado al que estoy escribiendo mi envoltorio está escrito en Java.
Combinando algunas de las otras respuestas que harán el truco: ninguna señal enviada a la aplicación principal se enviará al subproceso.
import os
from subprocess import Popen
def preexec(): # Don''t forward signals.
os.setpgrp()
Popen(''whatever'', preexec_fn = preexec)
Intente configurar SIGINT para ignorarlo antes de generar el subproceso (restablecerlo a su comportamiento predeterminado más adelante).
Si eso no funciona, deberá leer el control del trabajo y aprender a poner un proceso en su propio grupo de procesos en segundo plano, de modo que ^ C ni siquiera haga que el kernel le envíe la señal en el primer lugar. (Puede no ser posible en Python sin escribir C helpers).
Ver también esta pregunta anterior .
puedes hacer algo como esto para que funcione en Windows y Unix:
import subprocess
import sys
def pre_exec():
# To ignore CTRL+C signal in the new process
signal.signal(signal.SIGINT, signal.SIG_IGN)
if sys.platform.startswith(''win''):
#https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx
#CREATE_NEW_PROCESS_GROUP=0x00000200 -> If this flag is specified, CTRL+C signals will be disabled
my_sub_process=subprocess.Popen(["executable"], creationflags=0x00000200)
else:
my_sub_process=subprocess.Popen(["executable"], preexec_fn = pre_exec)