2013-10-29 17 views
7

Sto scrivendo uno script python che deve eseguire una discussione che ascolta un socket di rete.Programma Python con thread non in grado di catturare CTRL + C

Ho problemi con l'uccisione utilizzando Ctrl +c usando il codice seguente:

#!/usr/bin/python 

import signal, sys, threading 

THREADS = [] 

def handler(signal, frame): 
    global THREADS 
    print "Ctrl-C.... Exiting" 
    for t in THREADS: 
     t.alive = False 
    sys.exit(0) 

class thread(threading.Thread): 
    def __init__(self): 
     self.alive = True 
     threading.Thread.__init__(self) 


    def run(self): 
     while self.alive: 
      # do something 
      pass 

def main(): 
    global THREADS 
    t = thread() 
    t.start() 
    THREADS.append(t) 

if __name__ == '__main__': 
    signal.signal(signal.SIGINT, handler) 
    main() 

Apprezziamo qualsiasi consigli su come catturare Ctrl +c e terminare lo script .

risposta

3

È perché i segnali possono essere catturati solo dalla filettatura principale. E qui il thread principale ha concluso la sua vita molto tempo fa (l'applicazione è in attesa che il tuo thread finisca). Prova ad aggiungere

while True: 
    sleep(1) 

alla fine del vostro main() (e naturalmente from time import sleep in cima).

o come Kevin detta:

for t in THREADS: 
    t.join(1) # join with timeout. Without timeout signal cannot be caught. 
+0

L'uso di 'Thread.join()' è preferibile su spin-looping con timeout. –

+0

perché i segnali possono essere catturati solo dal thread principale? – tristan

+1

http://docs.python.org/2/library/signal.html 7 ° punto. Prendilo come una legge :) – jaor

8

Il problema è che, dopo l'esecuzione cade il filo principale (dopo main() restituito), il modulo threading entrerà in pausa, in attesa che gli altri thread per finire, utilizzando serrature ; e le serrature non possono essere interrotte con i segnali. Questo è il caso in Python 2.x almeno.

Una soluzione semplice è quella di evitare di cadere dal thread principale, aggiungendo un ciclo infinito che chiama alcune funzioni che dormono finché non è disponibile un'azione, come select.select(). Se non hai bisogno del thread principale per fare nulla, usa signal.pause(). Esempio:

if __name__ == '__main__': 
    signal.signal(signal.SIGINT, handler) 
    main() 
    while True:   # added 
     signal.pause() # added 
Problemi correlati