2009-11-02 8 views
7

Por alguna razón, siginterrupt() solo parece establecer el comportamiento de la primera señal recibida.siginterrupt() solo funciona para la primera señal? (Python)

En este programa de ejemplo, el primer SIGQUIT parece no hacer nada, pero el segundo sigquit imprime "SIGQUIT Handler" y s.accept() arroja una excepción de llamada al sistema interrumpido.

from signal import * 
from socket import * 
import sys 

def sigquitHandler(signum, frame): 
     print("SIGQUIT Handler") 

s = socket() 
s.bind(("0.0.0.0", int(sys.argv[1]))) 
s.listen(5) 

signal(SIGQUIT, sigquitHandler) 
siginterrupt(SIGQUIT, False) 

client, addr = s.accept() # Or any syscall that blocks 
client.close() 
s.close() 

¿Qué estoy mal entendiendo aquí?


Editar: Aquí hay algo más que no puedo entender, en este programa, un SIGQUIT interrumpe la selección(). ¿Se supone que eso suceda?

from signal import * 
import select 
import sys 

def sigquitHandler(signum, frame): 
    print("SIGQUIT Handler") 

signal(SIGQUIT, sigquitHandler) 
siginterrupt(SIGQUIT, False) 

select.select([sys.stdin], [], []) 
+1

creo que 'siginterrupt' realmente sólo se aplica a las llamadas al sistema que impliquen la transferencia de datos (primitivas como abrir, leer o escribir). No creo que se aplique a llamadas al sistema como 'seleccionar'. – mhawke

+0

Ah, está bien. Gracias de nuevo :) –

Respuesta

2

¿Cuál unix estás usando? En el nivel C, hay diferentes implementaciones y semántica para el manejo de señal en BSD vs Sistema 5 (SYSV).

Supongo que está utilizando SYSV, en cuyo caso la disposición de la señal se reinicia a SIG_DFL después de que el manejador de señal haya regresado (manejo de señales clásico). En SYSV debe llamar al signal en el controlador para volver a instalar ese controlador.

Python proporciona, más o menos, el manejo de señal de estilo BSD. Por lo tanto, en un sistema operativo SYSV, Python debe administrar la reinstalación del manejador de señal a través del signal. Ahora, de acuerdo con la mana de Python para siginterrupt:

Tenga en cuenta que la instalación de un controlador de señal con la señal() se restablecerá el comportamiento de reinicio a interrumpible por siginterrupt implícitamente llamando al() con un verdadero valor del indicador para el dada la señal .

y ahí lo tienes - si Python se vuelve a instalar automáticamente el controlador de señal (para proporcionar BSD como la semántica), bien puede hacerlo de una manera que llama implícitamente siginterrupt(1).

Por supuesto, mi conjetura podría ser incorrecta.

Usted puede ser capaz de solucionar este problema mediante la definición de sigquitHandler así:

def sigquitHandler(signum, frame): 
    print("SIGQUIT Handler") 
    siginterrupt(SIGQUIT, False) 

Depende de cuándo y cómo Python es la restauración de la disposición de la señal.

EDITAR

Adición siginterrupt(SIGQUIT, False) al controlador de señal no tiene efecto.

EDIT 2

Después de un poco más de hurgando en el código fuente Python2.6 claro que esto no es sólo una cuestión SYSV. También afectará los sistemas BSD.

+0

Eso tiene sentido, ¡gracias! –

4

Es un bug de python."siginterrupt with flag = False se restablece cuando se recibe la señal", que se ha corregido en la versión posterior de python2.6. (2.6.6+, 2.7+)

Para el segundo, siginterrupt no afecta a select().

ver http://lkml.org/lkml/2005/7/23/119

Cuestiones relacionadas