在父线程中引发异常

3
我遇到了一个问题,一个方法调用一直阻塞不释放。很不幸,导致这个问题的bug并没有确切的解决方法,因此目前的解决方法是设置一个超时时间。
我尝试通过注册计时器,并在其触发时抛出异常来中断阻塞的调用。然而,这会在计时器线程而不是主线程中引发异常。
它现在看起来像这样:
from threading import Timer

def timeoutSocket():
    raise InterruptedError


socketDeadlockDetector = Timer(DEADLOCK_TIMEOUT, timeoutSocket)
socketDeadlockDetector.start()

# receive and unpack data
try:
    packet = server.receive()
except InterruptedError:
    print("Interrupted socket receive, continuing")
    continue

socketDeadlockDetector.cancel()

server.receive() 是一个不应该阻塞的方法。然而,当我运行这个方法时,socketDeadlockDetector 线程会自行中断而不影响原始线程。

有没有办法将此异常传递给父级?


这是什么操作系统?接收代码是否可以使用“select”轮询套接字而不是进行阻塞读取?在某些平台上,您无法唤醒某些类型设备上的阻塞读取(“不可中断等待”状态)。 - Daniel Pryden
这是一个奇怪的TCP错误,其中套接字被打开,发送方认为数据已发送并因此关闭了套接字,但由于某种原因,接收方(服务器)没有关闭套接字,并且挂起了。这不是套接字超时本身,因此据我所知,没有套接字技巧可以解决它。 - Brydon Gibson
听起来像是套接字半关闭吗?无论如何,如果您的接收器在循环中使用 select.select(),那么它有机会运行其他代码(例如,检查超时是否已过期),在检查是否有更多数据可以从套接字中读取之间。 - Daniel Pryden
好的,我已经了解了这个问题,现在我知道它是如何工作的,谢谢! - Brydon Gibson
1个回答

0

Timer 创建一个线程来运行函数。抛出异常没有任何作用,因为那不是需要中断的线程。当超时发生时,您需要取消在另一个线程中阻塞的任何内容。在这种情况下,它是一个套接字,因此杀死套接字应该可以解决问题。

import struct

def timeoutSocket():
    # enable linger with timeout 0 to send RESET on close
    server.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
    server.close()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接