import asyncio import functools import random import signal import subprocess import sys import time TIMEOUT = 5 def _finish_future(fut, value, *args): if fut.done(): return fut.set_result(value) def _sig_chld(fut, start_time, signum, frame): elapsed = time.time() - start_time if elapsed > TIMEOUT: # Then the signal handler wasn't called when it should. return finish_future = functools.partial(_finish_future, fut, elapsed) loop.call_soon_threadsafe(finish_future) async def run(loop): steps = random.randrange(152, 160) args = [sys.executable, '-c', 'import time; time.sleep(3600)'] popen = subprocess.Popen(args) pid = popen.pid waiter = loop.create_future() handle_signal = functools.partial(_sig_chld, waiter, time.time()) signal.signal(signal.SIGCHLD, handle_signal) timeout_handle = loop.call_later(TIMEOUT, _finish_future, waiter, 'timeout') print(f'killing pid: {pid!r}') popen.kill() i = 0 while i < steps: i += 1 try: print('awaiting future') await waiter print(f'steps: {steps}') result = waiter.result() if result == 'timeout': print('timed out') exit() print(f'result: {result:.6f}') finally: timeout_handle.cancel() popen.wait() async def main(loop): i = 1 start = time.time() while True: elapsed = time.time() - start print(f'[{i}]: {elapsed:.2f}') await run(loop) time.sleep(0.1) i += 1 loop = asyncio.new_event_loop() loop.run_until_complete(main(loop))