Python – No se puede matar el hilo principal con KeyboardInterrupt

Estoy haciendo un escáner de puerto multiproceso simple. Analiza todos los puertos en el host y devuelve los puertos abiertos. El problema es interrumpir el escaneo. Lleva mucho tiempo completar una exploración y, a veces, deseo eliminar el progtwig con Cc mientras se está realizando la exploración. El problema es que la exploración no se detendrá. El subproceso principal está bloqueado en queue.join () y se olvida de KeyboardInterrupt, hasta que todos los datos de la cola se procesan, desbloqueando así el subproceso principal y saliendo del progtwig con gracia. Todos mis hilos están demonizados, así que cuando el hilo principal muere, ellos deberían morir con él.

Intenté usar la señal lib, sin éxito. La anulación de subprocesos. La clase de subprocesos y el método de adición para una terminación elegante no funcionaron … El subproceso principal simplemente no recibe KeyboardInterrupt mientras se ejecuta queue.join ()

import threading, sys, Queue, socket queue = Queue.Queue() def scan(host): while True: port = queue.get() if port > 999 and port % 1000 == 0: print port try: #sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #sock.settimeout(2) #you need timeout or else it will try to connect forever! #sock.connect((host, port)) #----OR---- sock = socket.create_connection((host, port), timeout = 2) sock.send('aaa') data = sock.recv(100) print "Port {} open, message: {}".format(port, data) sock.shutdown() sock.close() queue.task_done() except: queue.task_done() def main(host): #populate queue for i in range(1, 65536): queue.put(i) #spawn worker threads for port in range(100): t = threading.Thread(target = scan, args = (host,)) t.daemon = True t.start() if __name__ == '__main__': host = "" #does input exist? try: host = sys.argv[1] except: print "No argument was recivied!" exit(1) #is input sane? try: host = socket.gethostbyname(host) except: print "Adress does not exist" exit(2) #execute main program and wait for scan to complete main(host) print "Post main() call!" try: queue.join() except KeyboardInterrupt: print "CC" exit(3) 

EDITAR:

He encontrado una solución utilizando el módulo de tiempo.

 #execute main program and wait for scan to complete main(host) #a little trick. queue.join() makes main thread immune to keyboardinterrupt. So use queue.empty() with time.sleep() #queue.empty() is "unreliable" so it may return True a bit earlier then intented. #when queue is true, queue.join() is executed, to confirm that all data was processed. #not a true solution, you can't interrupt main thread near the end of scan (when queue.empty() returns True) try: while True: if queue.empty() == False: time.sleep(1) else: break except KeyboardInterrupt: print "Alas poor port scanner..." exit(1) queue.join() 

Ya creaste tus daemons de hilos, pero necesitas mantener vivo tu hilo principal mientras hay hilos de daemon, hay cómo hacerlo: No puedes matar el script de Python con Ctrl-C

Cuando cree los subprocesos, agréguelos a una lista de subprocesos en ejecución y cuando trate con ctrl-C, envíe una señal de interrupción a cada subproceso de la lista. De esa manera usted está limpiando activamente en lugar de confiar en que se haga por usted.