2009-11-02 4 views
7

Per qualche ragione, siginterrupt() sembra solo impostare il comportamento per il primo segnale ricevuto.siginterrupt() funziona solo per il primo segnale? (Python)

In questo programma di esempio, il primo SIGQUIT sembra non eseguire nulla, ma il secondo sigquit stampa "SIGQUIT Handler" e s.accept() genera un'eccezione di chiamata di sistema interrotta.

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() 

Cosa sto fraintendendo qui?


Edit: Ecco un'altra cosa che io non riesco a capire, in questo programma, un SIGQUIT interrompe il select(). Dovrebbe succedere?

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

penso che 'siginterrupt' realmente si applica solo alle chiamate di sistema che coinvolgono il trasferimento dei dati (primitive come apertura, lettura o scrittura). Non penso che si applichi alle chiamate di sistema come 'select'. – mhawke

+0

Ah, ok. Grazie ancora :) –

risposta

2

Which unix stai usando? Al livello C, esistono diverse implementazioni e semantica per la gestione dei segnali su BSD rispetto a Sistema 5 (SYSV).

La mia ipotesi è che si sta utilizzando SYSV, nel qual caso la disposizione del segnale viene reimpostata su SIG_DFL dopo che il gestore di segnali è tornato (gestione del segnale classica). Su SYSV è necessario chiamare signal nel gestore per reinstallare il gestore.

Python fornisce più o meno la gestione del segnale in stile BSD. Quindi, su un sistema operativo SYSV, Python deve gestire la reinstallazione del gestore di segnale tramite signal. Ora, secondo il doco Python per siginterrupt:

Si noti che l'installazione di un gestore di segnale con il segnale() si resetta il comportamento di riavvio a interrompibile da siginterrupt implicitamente chiama() con un vero e proprio valore flag per il dato il segnale .

e ci si va - se Python è la reinstallazione automaticamente il gestore di segnale (per fornire BSD come la semantica), si può ben farlo in un modo che richiama implicitamente siginterrupt(1).

Ovviamente, la mia ipotesi potrebbe essere sbagliata.

È potrebbe essere in grado di risolvere questo problema definendo sigquitHandler come questo:

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

Dipende da quando e come Python sta ripristinando la disposizione del segnale.

EDIT

Aggiunta siginterrupt(SIGQUIT, False) al gestore di segnale non ha alcun effetto.

EDIT 2

Dopo un po 'di più frugato nel codice sorgente python2.6 in chiaro che questo non è solo un problema di SYSV. Influirà anche sui sistemi BSD.

+0

Questo ha senso, grazie! –

4

È un bug di python."siginterrupt with flag = False viene ripristinato quando il segnale ricevuto", che è stato corretto nella successiva versione di python2.6. (2.6.6+, 2.7+)

Per il secondo, il siginterrupt non influisce su select().

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

Problemi correlati