python subprocess signals sigint keyboardinterrupt

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)