Sto facendo un semplice port scanner multi-thread. Esegue la scansione di tutte le porte sull'host e restituisce le porte aperte. Il problema sta interrompendo la scansione. Ci vuole molto tempo prima che una scansione sia completata e, a volte, desidero uccidere il programma con C-c mentre sono nel mezzo della scansione. Il problema è che la scansione non si fermerà. Il thread principale è bloccato su queue.join() e ignaro di KeyboardInterrupt, finché non vengono elaborati tutti i dati dalla coda, in modo da sbloccare il thread principale e uscire dal programma con garbo. Tutti i miei thread sono demonizzati, quindi quando il thread principale muore dovrebbero morire con lui.Python - Impossibile interrompere il thread principale con KeyboardInterrupt
Ho provato a utilizzare signal lib, non riuscito. Override classe threading.Thread e metodo per la terminazione aggraziato non ha funzionato l'aggiunta di ... thread principale solo non riceverà KeyboardInterrupt durante l'esecuzione 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 "C-C"
exit(3)
EDIT:
ho trovato un soluzione utilizzando il modulo del tempo.
#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()
Qualcuno sa se c'è un modo per fare questo senza un po 'di vero ? Questo spreca un sacco di CPU e sto usando Thread dal threading per evitare un po 'True. 'thread.join' è perfetto se solo potessi ucciderlo (senza un ciclo infinito di tempo per la CPU). Qualche idea? Il test che eseguirò non richiede che lo uccida perché il thread continua indefinitamente (teoricamente continuerà per sempre), tuttavia, per scopi di test e riferimenti futuri (dal momento che è un dolore fare 'pkill python' in un altro termine finestra ogni volta), mi piacerebbe davvero sapere. Grazie (e non dire ctrl + z) – dylnmc
Se stai eseguendo questo su Windows, questo è "normale". L'interprete Python cattura CTRL-C e imposta un flag interno, quindi attende che il controllo ritorni all'interpretazione di Python in modo che possa generare 'KeyboardInterrupt'. Si affida al blocco delle chiamate di sistema per restituire 'EINTR' per tornare indietro e controllare quella bandiera interna. Tuttavia, il blocco delle operazioni di sistema su Windows non viene restituito con un codice di errore 'EINTR' quando accade una cosa del genere, quindi l'eccezione' KeyboardInterrupt' viene ritardata fino al completamento dell'operazione di blocco. –