为什么time.sleep()在使用信号处理程序时会立即停止?

时间:2018-02-06 08:17:01

标签: python asynchronous signals fork

在做一些WSGI服务器时,我注意到在循环中对time.sleep()的一些测试调用仅在第一次迭代时才进行。这是一个复制品:

import os
import signal 
import time


def run_loop():
    i = 0
    while True:
        print('PID: {}, i = {}'.format(os.getpid(), i))
        time.sleep(5) # Only works the first time
        i += 1

        pid = os.fork() . # May or may not be related?
        if pid == 0:
            print('PID: {}, CHILD'.format(os.getpid(), i))
            os._exit(0)


if __name__ == '__main__':
    # If I uncomment this line it works fine.
    # If I leave it as is, the time.sleep in run_loop() only waits once. 
    signal.signal(signal.SIGCHLD, lambda a, b: os.wait())

    run_loop()

我知道time.sleep()文档中的以下部分。

  

实际暂停时间可能小于请求的时间,因为任何捕获的信号将在执行该信号的捕获程序后终止sleep()。

这是因为SIGCHLD信号在time.sleep()运行时一直触发吗?什么会导致信号取消每次调用time.sleep()一致?

1 个答案:

答案 0 :(得分:2)

来自linux睡眠文档

  

sleep()导致调用线程休眠,直到数量为止          以秒为单位指定的实时秒数已经过去或直到信号为止          到达时不被忽视。

有一个linux c函数,允许你在被称为' nanosleep'的信号打断后继续睡觉。它要么睡眠一定量的纳秒,要么睡觉直到信号到达并返回剩余的纳秒数但python不会在任何模块中暴露它

您可以自己模拟纳米睡眠所需的相同行为,例如:

import datetime
import time
def busy_sleep(seconds):
    start_time = datetime.datetime.now()
    seconds_slept = 0
    while seconds_slept < seconds:
        time.sleep(seconds - seconds_slept)
        seconds_slept = (datetime.datetime.now() - start_time).total_seconds()