2011-12-06 23 views
20

Ho eseguito il debug di un programma Python che segfaults dopo aver ricevuto un'eccezione KeyboardInterrupt. Questo viene normalmente eseguito premendo Ctrl + C dalla shell. Per verificare se un particolare cambiamento di codice ha corretto il bug, ho avuto un piccolo script di shell che ha inviato SIGINT al programma in un momento casuale dopo l'avvio. Il problema che ho è che l'invio di Ctrl + C sembra avere un effetto diverso sul programma rispetto all'invio del segnale SIGINT e quindi non causa la comparsa del bug, quindi mi chiedo quale sia la differenza tra le due azioni.Qual è la differenza tra Ctrl-C e SIGINT?

Il programma non cattura alcuna azione della tastiera, ed è solo un programma python con alcuni thread/processi in essi. Non installa gestori di segnale (anche se Python lo fa), e stty -aintr = ^C. Sospetto che potrebbe essere che Ctrl + C invii SIGINT a tutti i processi secondari/thread mentre kill -INT invia solo al processo primario, ma questo è il mio sospetto.

Ecco lo script della shell che invia lo 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

Non sono sicuro di quanta differenza sarebbe, ma il suo eventuale ctrl + c sta inviando 'SIGTERM' invece di' SIGINT'. Inoltre, quando gestisci l'eccezione stai pulendo correttamente i tuoi sottoprocessi/thread? Il modo in cui Python gestisce i thread non credo che sarebbe un errore seg, ma probabilmente è possibile con processi secondari. – David

+0

+ C può essere configurato, quindi controlla le impostazioni di 'stty -a', cerca' intr =^C', forse^C è impostato anche per qualcos'altro? – cdarke

+0

c'è del multithreading nel codice? – Casey

risposta

11

^C invia uno SIGINT a tutti i processi nel gruppo di processi in primo piano. Per fare l'equivalente con kill, è necessario inviare il segnale al gruppo di processi (concetto-livello di sistema operativo):

kill -SIGINT -<pid> 

o al lavoro (concetto a livello di shell, la pipeline è conclusa con &):

kill -SIGINT % 
+0

Questo era quello che stavo cercando, ma per ragioni sconosciute il codice continua a non segfault quando uso lo script automatico. Ho trovato il bug che causava il crash di python - la multiprocessing della libreria python è implementata con i thread e causa la segfault in gobject se non si chiama gobject.threads_init. Tuttavia, la domanda originale per me è rimasta un mistero come il motivo per cui il ctrl + c invocato manualmente ha attivato il bug, ma lo script automatizzato no. – Belorn

+2

Ci scusiamo per essere ottusi, ma cosa significa "%" in questo contesto? –

+1

@KevinCantwell: si riferisce al lavoro corrente, ovvero l'ultimo lavoro in background (avviato in background o arrestato mentre era in primo piano e quindi in background). – ninjalj

4

Come described here:

Python installa un piccolo numero di gestori di segnale per impostazione predefinita: SIGPIPE viene ignorato (così errori di scrittura su tubazioni e le prese possono essere riportati come eccezioni Python ordinari) e SIGINT è tradotto in un'eccezioneKeyboardInterrupt. Tutti questi possono essere ignorati.

modo, il comportamento dovrebbe essere la stessa tra l'invio di un SIGINT e una Ctrl +c.

Ma, è necessario stare attenti con il KeyboardInterrupt, se da qualche parte nel codice hai un

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

questo sarà "mangiare" l'eccezione KeyboardInterrupt.

+0

Grazie per il consiglio. ho trovato una riga per farlo, e penso che risolverà un bug non correlato. Ma anche con quello commentato, il problema principale con segfault è ancora lì, e il più strano che l'invio di kill -INT non lo attiva ma ctrl + c lo fa. – Belorn

Problemi correlati