2011-12-06 12 views
20

He estado depurando un programa de Python que segfaults después de recibir una excepción KeyboardInterrupt. Esto normalmente se hace presionando Ctrl + C desde el shell. Para probar si un cambio de código en particular solucionó el error, tuve un pequeño script de shell que envió SIGINT al programa en un momento aleatorio después de la puesta en marcha. El problema que tengo es que enviar Ctrl + C parece tener un efecto diferente en el programa que enviar la señal SIGINT y por lo tanto no está causando la aparición del error, así que me pregunto cuál es la diferencia entre las dos acciones.¿Cuál es la diferencia entre Ctrl-C y SIGINT?

El programa no capta ninguna acción de teclado, y es solo un programa de Python con algunos subprocesos/procesos en ellos. No instala controladores de señal (aunque Python sí), y stty -a da intr = ^C. Sospecho que podría ser que Ctrl + C envíe SIGINT a todos los subprocesos/subprocesos, mientras que kill -INT solo envía al proceso primario, pero eso es lo que yo sospecho.

Aquí está el script de shell que envía el kill -INT.

wait 
while :; do 
    seconds="$(python -c 'import random; print random.random()*4')" 
    ./mandos --debug --configdir=confdir \ 
      --statedir=statedir --no-restore --no-dbus & 
    pid=$! 
    { sleep $seconds; kill -INT $pid; } & 
    fg %./mandos 
    status=$? 
    if [ $status -gt 1 ]; then 
     echo "Failed exit $status after $seconds seconds" 
     break 
    fi 
    wait 
done 
+0

No estoy seguro de la diferencia que esto sería, pero es posible que ctrl + c esté enviando 'SIGTERM' en lugar de' SIGINT'. Además, al manejar la excepción, ¿está limpiando correctamente sus subprocesos/subprocesos? La forma en que python maneja los hilos no creo que seg-fault, pero probablemente sea posible con subprocesos. – David

+0

+ C se puede configurar, entonces verifique su configuración 'stty -a', busque' intr =^C', tal vez^C también esté configurado para otra cosa? – cdarke

+0

¿hay algún multihilo en el código? – Casey

Respuesta

11

envía un SIGINT a todos los procesos en el grupo de proceso en primer plano. Para hacer el equivalente con kill, debe enviar la señal al grupo de procesos (concepto de nivel de sistema operativo):

kill -SIGINT -<pid> 

o al trabajo (concepto a nivel de la cáscara, la tubería terminó con &):

kill -SIGINT % 
+0

Esto era lo que estaba buscando, pero por razones desconocidas, el código todavía no segfault cuando uso el script automatizado. Descubrí que el error que causa python se bloquea: el multiprocesamiento de la biblioteca de Python se implementa con subprocesos y provoca segfaults en gobject si no se llama a gobject.threads_init. Aún así, la pregunta original para mí se deja como un misterio, porque el ctrl + c invocado manualmente activó el error, pero el script automatizado no lo hizo. – Belorn

+2

Lo siento por ser obtuso, pero ¿qué significa el '%' en este contexto? –

+1

@KevinCantwell: se refiere al trabajo actual, es decir, el último trabajo de fondo (ya sea iniciado en segundo plano, o detenido mientras estaba en primer plano, y por lo tanto en segundo plano). – ninjalj

4

Como described here:

Python instala un pequeño número de manejadores de señales por defecto: SIGPIPE se ignora (Así que escribe los errores en las tuberías y tomas de corriente pueden ser reportados como excepciones Python ordinarias) y SIGINT se traduce en una excepción KeyboardInterrupt. Todos estos pueden ser anulados.

así, el comportamiento debe ser la misma entre el envío de un SIGINT y una Ctrl +c.

Pero, usted tiene que tener cuidado con el KeyboardInterrupt, si en algún lugar de su código que tienes un

try: 
    ... 
except: # notice the lack of exception class 
    pass 

esto va a "comer" la excepción KeyboardInterrupt.

+0

Gracias por el consejo. encontré una línea haciendo eso, y creo que arreglará un error no relacionado. Pero incluso con eso comentado, el problema principal con segfault sigue ahí, y el más extraño es que enviar kill -INT no lo desencadena, pero ctrl + c sí lo hace. – Belorn

Cuestiones relacionadas