While doing some messing around with making a WSGI server, I noticed some test calls to time.sleep() inside a loop were only working the first iteration. Here's a reproduction:

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))

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())


I am aware of the following part in the time.sleep() documentation.


Is this because the SIGCHLD signal keeps triggering while time.sleep() is running? What would cause the signal to cancel every single call to time.sleep() consistently?


from the linux sleep documentation

sleep() causes the calling thread to sleep either until the number of real-time seconds specified in seconds have elapsed or until a signal arrives which is not ignored.

there is a linux c function that allows you to continue sleeping after being interrupted by a signal called 'nanosleep'. it either sleeps a given amount of nanoseconds or sleeps until a signal arrives and returns the number of nanoseconds that remain to be slept but python doesn't expose it in any module

you could simulate the same behavior you would want from nanosleep yourself, something like:

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()
  • I see what's going on. However, does this mean the signal is arriving at the same time sleep() is waiting every single time? Would this happen just by "luck", or can I expect the sleep() to be consistently interrupted in this case? – SamuelN Feb 6 '18 at 17:25
  • 1
    since the child process basically has no code to run it will always terminate before 5 seconds are passed, but depending on your os and cpu it could be possible for the signal to arrive before you start the sleep, but i wouldn't count on that – AntiMatterDynamite Feb 7 '18 at 9:12

Your Answer

