12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485 |
- #!/usr/bin/env python
- """
- Use to put a timeout on the length of time a script can run. This is
- especially useful for checking for scripts that hang.
- Usage
- =====
- NOTE: Make sure you run ``pip install -r requirements-dev.txt`` before running.
- To use the script, run::
- ./timeout "./my-script-to-run" --timeout-after 5
- """
- import argparse
- import os
- import subprocess
- import sys
- import time
- import psutil
- class TimeoutException(Exception):
- def __init__(self, timeout_len):
- msg = 'Script failed to complete within %s seconds' % timeout_len
- Exception.__init__(self, msg)
- def timeout(args):
- parent_pid = os.getpid()
- child_p = run_script(args)
- try:
- run_timeout(child_p.pid, args.timeout_after)
- except (TimeoutException, KeyboardInterrupt) as e:
- proc = psutil.Process(parent_pid)
- procs = proc.children(recursive=True)
- for child in procs:
- child.terminate()
- gone, alive = psutil.wait_procs(procs, timeout=1)
- for child in alive:
- child.kill()
- raise e
- def run_timeout(pid, timeout_len):
- p = psutil.Process(pid)
- start_time = time.time()
- while p.is_running():
- if p.status() == psutil.STATUS_ZOMBIE:
- p.kill()
- break
- current_time = time.time()
- # Raise a timeout if the duration of the process is longer than
- # the desired timeout.
- if current_time - start_time > timeout_len:
- raise TimeoutException(timeout_len)
- time.sleep(1)
- def run_script(args):
- return subprocess.Popen(args.script, shell=True)
- def main():
- parser = argparse.ArgumentParser(usage=__doc__)
- parser.add_argument('script', help='The script to run for benchmarking')
- parser.add_argument(
- '--timeout-after',
- required=True,
- type=float,
- help=(
- 'The length of time in seconds allowed for the script to run '
- 'before it time\'s out.'
- ),
- )
- args = parser.parse_args()
- return timeout(args)
- if __name__ == '__main__':
- sys.exit(main())
|