2009-07-28 23 views
6

Si le digo a Perl para ignorar una señal de forma explícita, SIGINT no tiene ningún efecto:¿Cuál es la diferencia entre ignorar una señal y decirle que no haga nada en Perl?

$SIG{INT} = 'IGNORE'; 
my $count = 0; 
say $count++ and sleep 1 while 1; 

A continuación, pulsar Control-C, en lugar obviamente, no tiene ningún efecto. Si, por otro lado, le digo que no haga nada:

$SIG{INT} = sub { }; 
my $count = 0; 
say $count++ and sleep 1 while 1; 

¡Entonces presionar Control-C tiene un efecto! Despierta el programa de su llamada sleep() e inmediatamente incrementa el conteo. ¿Cuál es la diferencia entre ignorar una señal y decirle que no haga nada?

En mi programa, me gustaría tener el código ejecutado en SIGINT, sin que lo interrumpa todo. Quiero algo como:

$SIG{INT} = sub { say "Caught SIGINT!"; return IGNORED; }; # runs without disrupting sleep 
+0

¿Cómo podría funcionar su manejador de señal sin interrumpir lo que se está ejecutando actualmente? La lógica de manejo de señal tendrá que saber lo que se supone que sucederá ANTES de que se produzca la señal. – innaM

Respuesta

1

No sé por qué no está funcionando como se espera, pero normalmente cuando intento para lograr cosas similares que también atrapan la señal TERM, además de la señal INT.

13

¿Cuál es la diferencia entre ignorar una señal y decirle que no haga nada?

Su controlador "no hacer nada" todavía se invoca cuando se entrega la señal, interrumpiendo la llamada sleep en este caso. Las señales ignoradas, por otro lado, simplemente son descartadas por el sistema, sin tener ningún efecto en el proceso.

Consulte here para obtener una referencia específica de C pero más completa.

6

Muchas de las llamadas al sistema pueden ser interrumpidas por la entrega de la señal. Por lo general, puede marcar $! (también conocido como errno) para ver si es EINTR y tomar medidas para volver a intentar la llamada al sistema fallida.

Si es importante para usted que ciertas secciones de su código (en este caso, su llamada al sleep()) no se interrumpen, puede usar POSIX::sigprocmask para bloquear las señales mientras se encuentra en su sección crítica. Todas las señales recibidas por la aplicación serán puestas en cola hasta que las desbloquees, en ese punto serán entregadas. Estoy bastante seguro de que hay algunas semánticas divertidas cuando se bloquean múltiples señales de un tipo en particular (creo que pueden fusionarse en una sola señal).

Aquí hay un nice primer de IBM sobre las funciones de reentrantes, e incluye una pequeña muestra con sigprocmask.

+0

+1. Según tengo entendido, la mayoría de las variantes de UNIX fusionarán por completo múltiples señales del mismo tipo. Entonces, cuando veas una señal XYZ, de lo único que puedes estar seguro es de que XYZ se elevó * al menos una vez *. –

Cuestiones relacionadas