~andrewjbeach/juju-ci-tools/make-local-patcher

« back to all changes in this revision

Viewing changes to timeout.py

  • Committer: John George
  • Date: 2015-01-14 22:03:47 UTC
  • mto: This revision was merged to the branch mainline in revision 798.
  • Revision ID: john.george@canonical.com-20150114220347-e8q5wezs1qg9a00u
Added support for setting the juju path, series and agent_url.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
"""A Python implementation of the *nix utility for use on all platforms."""
3
 
from argparse import ArgumentParser
4
 
from itertools import chain
5
 
import signal
6
 
import subprocess
7
 
import sys
8
 
import time
9
 
 
10
 
from utility import until_timeout
11
 
 
12
 
 
13
 
# Generate a list of all signals that can be used with Popen.send_signal on
14
 
# this platform.
15
 
if sys.platform == 'win32':
16
 
    signals = {
17
 
        'TERM': signal.SIGTERM,
18
 
        # CTRL_C_EVENT is also supposed to work, but experience shows
19
 
        # otherwise.
20
 
        'CTRL_BREAK': signal.CTRL_BREAK_EVENT,
21
 
        }
22
 
else:
23
 
    # Blech.  No equivalent of errno.errorcode for signals.
24
 
    signals = dict(
25
 
        (x[3:], getattr(signal, x)) for x in dir(signal) if
26
 
        x.startswith('SIG') and x not in ('SIG_DFL', 'SIG_IGN'))
27
 
 
28
 
 
29
 
def parse_args(argv=None):
30
 
    parser = ArgumentParser()
31
 
    parser.add_argument('duration', type=float)
32
 
 
33
 
    parser.add_argument(
34
 
        '--signal', default='TERM', choices=sorted(signals.keys()))
35
 
    return parser.parse_known_args(argv)
36
 
 
37
 
 
38
 
def run_command(duration, timeout_signal, command):
39
 
    """Run a subprocess.  If a timeout elapses, send specified signal.
40
 
 
41
 
    :param duration: Timeout in seconds.
42
 
    :param timeout_signal: Signal to send to the subprocess on timeout.
43
 
    :param command: Subprocess to run (Popen args).
44
 
    :return: exit status of the subprocess, 124 if the subprocess was
45
 
        signalled.
46
 
    """
47
 
    if sys.platform == 'win32':
48
 
        # support CTRL_BREAK
49
 
        creationflags = subprocess.CREATE_NEW_PROCESS_GROUP
50
 
    else:
51
 
        creationflags = 0
52
 
    proc = subprocess.Popen(command, creationflags=creationflags)
53
 
    for remaining in chain([None], until_timeout(duration)):
54
 
        result = proc.poll()
55
 
        if result is not None:
56
 
            return result
57
 
        time.sleep(0.1)
58
 
    else:
59
 
        proc.send_signal(timeout_signal)
60
 
        proc.wait()
61
 
        return 124
62
 
 
63
 
 
64
 
def main(args=None):
65
 
    args, command = parse_args(args)
66
 
    return run_command(args.duration, signals[args.signal], command)
67
 
 
68
 
 
69
 
if __name__ == '__main__':
70
 
    sys.exit(main())