关于多线程:Python – 无法使用KeyboardInterrupt杀死主线程

Python - Can't kill main thread with KeyboardInterrupt

我正在制作一个简单的多线程端口扫描器。 它扫描主机上的所有端口并返回打开的端口。 麻烦在于中断扫描。 扫描完成需要花费大量时间,有时我希望在扫描过程中用C-c杀死程序。 麻烦的是扫描不会停止。 主线程被锁定在queue.join()上,并且忘记了KeyboardInterrupt,直到处理了队列中的所有数据,因此解除了主线程并正常退出程序。 我的所有线程都被守护进来,所以当主线程死掉时,他们应该和他一起死掉。

我尝试使用信号库,没有成功。 重写threading.Thread类和正常终止的添加方法不起作用...主线程在执行queue.join()时不会收到KeyboardInterrupt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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)

编辑:

我通过使用时间模块找到了解决方案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#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()


你已经创建了你的线程守护进程,但你需要保持主线程处于活动状态,而守护程序线程就在那里,有如何做到这一点:不能用Ctrl-C杀死Python脚本


创建线程时,将它们添加到正在运行的线程列表中,当处理ctrl-C时,向列表中的每个线程发送一个kill信号。 这样你就可以积极清理而不是依赖它为你完成。