套接字连接期间处理信号

时间:2018-12-16 19:08:00

标签: python python-3.x sockets signals python-sockets

我正在尝试处理Python脚本中的信号接收,以进行清理并正常退出。该脚本利用了许多socket连接,我意识到这些连接可能在发出信号期间正在运行,因此需要对此进行调查。具体来说,等待网络响应的操作将立即退出,以便程序可以及时响应信号。

幸运的是,据我的研究使我相信,似乎在任何系统调用(例如在socket.connect()中,立即调用信号处理程序将被中断。此外,在Python中,如果信号处理程序引发异常,则该异常会从进行系统调用的代码中传播出去。

因此,我准备了以下代码来测试在出现信号的情况下是否等待网络响应。我们通过尝试在无法响应的端口上连接Google来模拟长时间的网络等待/超时。在等待期间,异步引发退出信号(CTRL_C_EVENT,该信号由SIGINT处理,因为我当前正在使用Windows)。信号处理程序将被调用并通过SystemExit引发sys.exit()异常,然后应将其抛出socket.connect()并加以捕获,然后程序正常退出。

import os
import signal
import socket
import sys
import threading
import time

def kill():
    print("Raising signal at {}".format(time.time()))
    os.kill(os.getpid(), signal.CTRL_C_EVENT)

def handler(signo, frame):
    print("Handling signal at {}".format(time.time()))
    sys.exit()


signal.signal(signal.SIGINT, handler)

t = threading.Timer(5, kill)

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(10)

    print("Connecting at {}".format(time.time()))
    t.start()
    s.connect(("www.google.com", 81))
    print("Connected at {}".format(time.time()))
except SystemExit as e:
    print("Caught SystemExit at {}".format(time.time()))
    raise e

我希望程序会输出以下内容:

Connecting at <some time A>
Raising signal at <~5s after A>
Handling signal at <~5s after A>
Caught SystemExit at <~5s after A>
<program exits>

但是我实际得到的一个例子是:

Connecting at 1544985636.4006333
Raising signal at 1544985641.4017904
Handling signal at 1544985646.4649496
<program exits>

您可以看到,不仅SystemExit异常神奇地消失在某个地方,而且信号处理程序在发出信号后5秒钟被调用!似乎socket.connect吞噬了信号然后超时,而不是立即中断(但是由于某种原因没有引发异常吗?)。

这种奇怪行为的原因是什么?收到信号后,如何获得退出socket.connect()的预期行为?

0 个答案:

没有答案