gpt4 book ai didi

python - Python 线程中的死锁

转载 作者:行者123 更新时间:2023-11-30 23:47:42 29 4
gpt4 key购买 nike

我正在尝试用 Python 实现一个简单的端口扫描器。它的工作原理是创建许多工作线程来扫描队列中提供的端口。他们将结果保存在另一个队列中。当所有端口都被扫描时,线程和应用程序应该终止。问题就在这里:对于少量端口,一切正常,但如果我尝试扫描 200 个或更多端口,应用程序将陷入死锁。我不知道为什么。

class ConnectScan(threading.Thread):
def __init__(self, to_scan, scanned):
threading.Thread.__init__(self)
self.to_scan = to_scan
self.scanned = scanned

def run(self):
while True:
try:
host, port = self.to_scan.get()
except Queue.Empty:
break
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((host, port))
s.close()
self.scanned.put((host, port, 'open'))
except socket.error:
self.scanned.put((host, port, 'closed'))
self.to_scan.task_done()


class ConnectScanner(object):
def scan(self, host, port_from, port_to):
to_scan = Queue.Queue()
scanned = Queue.Queue()
for port in range(port_from, port_to + 1):
to_scan.put((host, port))
for i in range(20):
ConnectScan(to_scan, scanned).start()
to_scan.join()

有人看出可能出了什么问题吗?另外,我希望得到一些如何在 Python 中调试此类线程问题的提示。

最佳答案

我没有发现您的代码有任何明显的错误,但就目前情况而言,永远不会遇到中断 - self.to_scan.get() 将永远等待而不是引发 Queue.Empty。鉴于您要在启动线程之前加载要扫描的端口队列,您可以将其更改为 self.to_scan.get(False) 以使工作线程在所有端口都已正确退出时正确退出已被认领。

结合您拥有非守护线程(在主线程完成后使进程保持事件状态的线程)这一事实,这可能是挂起的原因。尝试在 to_scan.join() 之后打印一些内容,看看它是否停止在那里,或者在进程退出时停止。

正如 Ray 所说,如果在 self.to_scan.get()self.to_scan.task_done() 之间引发除 socket.error 之外的异常,则join 调用将挂起。它可以帮助更改该代码以使用 try/finally 来确定:

def run(self):
while True:
try:
host, port = self.to_scan.get(False)
except Queue.Empty:
break

try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((host, port))
s.close()
self.scanned.put((host, port, 'open'))
except socket.error:
self.scanned.put((host, port, 'closed'))
finally:
self.to_scan.task_done()

一般来说,调试多线程进程是很棘手的。我试图避免任何无限期的阻塞 - 最好是让某些东西因为超时太短而大声崩溃,而不是让它永远停止等待永远不会出现的项目。因此,我会为您的 self.to_scan.getsocket.connectto_scan.join 调用指定超时。

使用日志记录来确定事件发生的顺序 - 打印可以从不同的线程交错,但记录器是线程安全的。

另外,类似 this recipe可以方便地转储每个线程的当前堆栈跟踪。

我还没有使用过任何支持在 Python 中调试多线程的调试器,但是列出了一些 here .

关于python - Python 线程中的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8275573/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com