sirve que para libreria examples ejemplo check_output python subprocess sigkill

python - que - Matando a los niños con el padre.



subprocess python 3 call (7)

En realidad, encontré que su enfoque original funcionó bien para mí: aquí está el código de ejemplo exacto que probé con el que funcionó:

echoer.py

#!/bin/env python import time import sys i = 0 try: while True: i += 1 print i time.sleep(1) except KeyboardInterrupt: print "/nechoer caught KeyboardInterrupt" exit(0)

parentProc.py

#!/bin/env python import ctypes import subprocess import time libc = ctypes.CDLL(''/lib64/libc.so.6'') PR_SET_PDEATHSIG = 1 SIGINT = 2 SIGTERM = 15 def set_death_signal(signal): libc.prctl(PR_SET_PDEATHSIG, signal) def set_death_signal_int(): set_death_signal(SIGINT) def set_death_signal_term(): set_death_signal(SIGTERM) #subprocess.Popen([''./echoer.py''], preexec_fn=set_death_signal_term) subprocess.Popen([''./echoer.py''], preexec_fn=set_death_signal_int) time.sleep(1.5) print "parentProc exiting..."

Tengo un programa que genera y se comunica con procesos pesados ​​e inestables de la CPU, no creados por mí. Si mi aplicación falla o es asesinada por SIGKILL , quiero que también se eliminen los subprocesos, para que el usuario no tenga que rastrearlos y matarlos manualmente.

Sé que este tema ha sido cubierto anteriormente, pero he probado todos los métodos descritos y ninguno de ellos parece estar a la altura de sobrevivir a la prueba.

Sé que debe ser posible, ya que las terminales lo hacen todo el tiempo. Si ejecuto algo en un terminal y mato al terminal, las cosas siempre mueren.

He intentado atexit , doble horquilla y ptys . atexit no funciona para sigkill ; doble tenedor no funciona en absoluto; y ptys no he encontrado manera de trabajar con Python.

Hoy, me enteré de prctl(PR_SET_PDEATHSIG, SIGKILL) , que debería ser una forma para que los procesos secundarios prctl(PR_SET_PDEATHSIG, SIGKILL) un asesinato en sí mismos, cuando su padre / madre muere. Intenté usarlo con popen , pero parece que no tiene ningún efecto:

import ctypes, subprocess libc = ctypes.CDLL(''/lib/libc.so.6'') PR_SET_PDEATHSIG = 1; TERM = 15 implant_bomb = lambda: libc.prctl(PR_SET_PDEATHSIG, TERM) subprocess.Popen([''gnuchess''], preexec_fn=implant_bomb)

En lo anterior, se crea el hijo y el padre sale. Ahora esperas que la gnuchess reciba un SIGKILL y muera, pero no lo hace. Todavía puedo encontrarlo en mi administrador de procesos usando 100% de CPU.

¿Alguien puede decirme si hay algún problema con mi uso de prctl ? ¿O sabe cómo las terminales logran matar a sus hijos?


Hay algunas restricciones de seguridad a tener en cuenta porque si llamamos setuid después de que execv el niño no puede recibir la señal. La lista completa de estas restricciones está here

buena suerte !
/ Mohamed


He visto formas muy desagradables de "limpiar" usando cosas como ps xuawww | grep myApp | awk ''{ print $1}'' | xargs -n1 kill -9 ps xuawww | grep myApp | awk ''{ print $1}'' | xargs -n1 kill -9

El proceso del cliente, si se abre, puede capturar SIG_PIPE y morir. Hay muchas maneras de hacerlo, pero realmente depende de muchos factores. Si lanza algún código de ping (ping al padre) en el hijo, puede asegurarse de que se emita un SIG_PIPE en caso de fallecimiento. Si lo atrapa, lo que debería, terminará. Necesitaría comunicación bidireccional para que esto funcione correctamente ... o para bloquear siempre contra el cliente como el originador de la comunicación. Si no quieres modificar al niño, ignora esto.

Suponiendo que no esperas que el intérprete de Python real sea segregado, puedes agregar cada PID a una secuencia y luego matar al salir. Esto debería ser seguro para salir e incluso excepciones no detectadas. Python tiene instalaciones para realizar el código de salida ... para la limpieza.

Aquí hay algunos desagradables más seguros: agregue cada PID secundario a un archivo, incluido su proceso maestro (archivo separado). Utilice el bloqueo de archivos. Cree un demonio de vigilancia que observe el estado de flock () de su pid principal. Si no está bloqueado, elimine todos los PID de la lista de PID de su hijo. Ejecutar el mismo código en el inicio.

Más desagradable: escriba los PID en los archivos, como se (./myMaster; ./killMyChildren) anteriormente, luego invoque su aplicación en un sub-shell: (./myMaster; ./killMyChildren)


Me pregunto si el indicador PR_SET_PDEATHSIG está PR_SET_PDEATHSIG , incluso aunque lo configure después de la fork (y antes del exec ), por lo que parece que los documentos no deberían borrarse.

Para probar esa teoría, puede intentar lo siguiente: use el mismo código para ejecutar un subproceso que está escrito en C y, básicamente, solo llama a prctl(PR_GET_PDEATHSIG, &result) e imprime el resultado.

Otra cosa que podría intentar: agregar ceros explícitos para arg3, arg4 y arg5 cuando llame a prctl . Es decir:

>>> implant_bomb = lambda: libc.prctl(PR_SET_PDEATHSIG, TERM, 0, 0, 0)


Pensé que la doble horquilla era desprenderse de una terminal de control. No estoy seguro de cómo estás tratando de usarlo.

Es un truco, pero siempre puedes llamar "ps" y buscar el nombre del proceso que intentas matar.


Sé que han pasado años, pero encontré una solución simple (un poco intrépida) para este problema. Desde su proceso principal, envolviendo todas sus llamadas alrededor de un programa C muy simple que llama a prctl () y luego exec () resuelve este problema en Linux. Yo lo llamo "yeshup":

#include <linux/prctl.h> #include <signal.h> #include <unistd.h> int main(int argc, char **argv) { if(argc < 2) return 1; prctl(PR_SET_PDEATHSIG, SIGHUP, 0, 0, 0); return execvp(argv[1], &argv[1]); }

Al generar los procesos secundarios de Python (o cualquier otro idioma), puede ejecutar "yeshup gnuchess [argments]". Encontrará que, cuando el proceso principal se interrumpe, todos sus procesos secundarios (deben) recibir SIGHUP correctamente.

Esto funciona porque Linux aceptará la llamada a prctl (no la borrará) incluso después de llamar a execvp (que efectivamente "transforma" el proceso yeshup en un proceso de gnuchess, o cualquier comando que especifique allí), a diferencia de fork ().


PR_SET_DEATHSIG prctl solo se puede configurar para este mismo proceso que se llama prctl , no para ningún otro proceso, incluidos los elementos PR_SET_DEATHSIG este proceso específico. La forma en que la página de manual a la que estoy señalando expresa esto es "Este valor se borra en una bifurcación ()"; por supuesto, la forma en que se generan otros procesos (en Linux y en cualquier otro sistema operativo Unix-y).

Si no tiene control sobre el código que desea ejecutar en los subprocesos (como sería el caso, esencialmente, para su ejemplo de gnuchess ), le sugiero que primero genere un pequeño proceso de "monitoreo" con la función de realizar un seguimiento de todos sus hermanos (su proceso padre puede avisar al monitor sobre los pids de esos hermanos a medida que los genera) y enviarles señales asesinas cuando el padre común muere (el monitor debe sondear eso, despertarse cada N segundos durante un N de su opción para verificar si el padre aún está vivo; use la opción de select para esperar más información del padre con un tiempo de espera de N segundos, dentro de un bucle).

No es trivial, pero esas tareas del sistema a menudo no lo son. Los terminales lo hacen de manera diferente (a través del concepto de "terminal de control" para un grupo de proceso) pero, por supuesto, es trivial para cualquier niño bloquear ESO (doble forks, nohup , etc.).