Python: Cómo evitar que los subprocesos reciban CTRL-C / Control-C / SIGINT

Actualmente estoy trabajando en un contenedor para un servidor dedicado que se ejecuta en el shell. La envoltura genera el proceso del servidor a través de un subproceso y observa y reactjs a su salida.

Al servidor dedicado se le debe dar explícitamente un comando para que se apague correctamente. Por lo tanto, CTRL-C no debe alcanzar el proceso del servidor.

Si capturo la excepción KeyboardInterrupt o sobrescribo el controlador SIGINT en python, el proceso del servidor aún recibe el CTRL-C y se detiene de inmediato.

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 de subprocess.Popen (…) :

Si preexec_fn se establece en un objeto invocable, este objeto se llamará en el proceso hijo justo antes de que se ejecute el hijo. (Unix solamente)

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: En realidad, no se impide que la señal llegue al subproceso. En cambio, el preexec_fn anterior sobrescribe el manejador predeterminado de la señal para que la señal se ignore. Por lo tanto, es posible que esta solución no funcione si el subproceso sobrescribe nuevamente el controlador SIGINT .

Otra nota: esta solución funciona para todo tipo de subprocesos, es decir, no está restringida a los subprocesos escritos en Python, también. Por ejemplo, el servidor dedicado para el que estoy escribiendo mi contenedor 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) 

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) 

Intente configurar SIGINT para que se ignore antes de generar el subproceso (restablézcalo a su comportamiento predeterminado después).

Si eso no funciona, tendrá que leer sobre el control del trabajo y aprender cómo colocar un proceso en su propio grupo de proceso en segundo plano, de modo que ^ C ni siquiera haga que el kernel le envíe la señal en el primer lugar. (Puede que no sea posible en Python sin escribir ayudantes de C).

Vea también esta vieja pregunta .