]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - packages/Python/lldbsuite/test/test_runner/test/inferior.py
Vendor import of lldb trunk r256945:
[FreeBSD/FreeBSD.git] / packages / Python / lldbsuite / test / test_runner / test / inferior.py
1 #!/usr/bin/env python
2 """Inferior program used by process control tests."""
3
4 from __future__ import print_function
5
6 import argparse
7 import datetime
8 import signal
9 import subprocess
10 import sys
11 import time
12
13
14 def parse_args(command_line):
15     """Parses the command line arguments given to it.
16
17     @param command_line a list of command line arguments to be parsed.
18
19     @return the argparse options dictionary.
20     """
21     parser = argparse.ArgumentParser()
22     parser.add_argument(
23         "--ignore-signal",
24         "-i",
25         dest="ignore_signals",
26         metavar="SIGNUM",
27         action="append",
28         type=int,
29         default=[],
30         help="ignore the given signal number (if possible)")
31     parser.add_argument(
32         "--launch-child-share-handles",
33         action="store_true",
34         help=("launch a child inferior.py that shares stdout/stderr/stdio and "
35               "never returns"))
36     parser.add_argument(
37         "--never-return",
38         action="store_true",
39         help="run in an infinite loop, never return")
40     parser.add_argument(
41         "--return-code",
42         "-r",
43         type=int,
44         default=0,
45         help="specify the return code for the inferior upon exit")
46     parser.add_argument(
47         "--sleep",
48         "-s",
49         metavar="SECONDS",
50         dest="sleep_seconds",
51         type=float,
52         help="sleep for SECONDS seconds before returning")
53     parser.add_argument(
54         "--verbose", "-v", action="store_true",
55         help="log verbose operation details to stdout")
56     return parser.parse_args(command_line)
57
58
59 def handle_ignore_signals(options, signals):
60     """Ignores any signals provided to it.
61
62     @param options the command line options parsed by the program.
63     General used to check flags for things like verbosity.
64
65     @param signals the list of signals to ignore.  Can be None or zero-length.
66     Entries should be type int.
67     """
68     if signals is None:
69         return
70
71     for signum in signals:
72         if options.verbose:
73             print("disabling signum {}".format(signum))
74         signal.signal(signum, signal.SIG_IGN)
75
76
77 def handle_sleep(options, sleep_seconds):
78     """Sleeps the number of seconds specified, restarting as needed.
79
80     @param options the command line options parsed by the program.
81     General used to check flags for things like verbosity.
82
83     @param sleep_seconds the number of seconds to sleep.  If None
84     or <= 0, no sleeping will occur.
85     """
86     if sleep_seconds is None:
87         return
88
89     if sleep_seconds <= 0:
90         return
91
92     end_time = datetime.datetime.now() + datetime.timedelta(0, sleep_seconds)
93     if options.verbose:
94         print("sleep end time: {}".format(end_time))
95
96     # Do sleep in a loop: signals can interrupt.
97     while datetime.datetime.now() < end_time:
98         # We'll wrap this in a try/catch so we don't encounter
99         # a race if a signal (ignored) knocks us out of this
100         # loop and causes us to return.
101         try:
102             sleep_interval = end_time - datetime.datetime.now()
103             sleep_seconds = sleep_interval.total_seconds()
104             if sleep_seconds > 0:
105                 time.sleep(sleep_seconds)
106         except:  # pylint: disable=bare-except
107             pass
108
109
110 def handle_launch_children(options):
111     if options.launch_child_share_handles:
112         # Launch the child, share our file handles.
113         # We won't bother reaping it since it will likely outlive us.
114         subprocess.Popen([sys.executable, __file__, "--never-return"])
115
116
117 def handle_never_return(options):
118     if not options.never_return:
119         return
120
121     # Loop forever.
122     while True:
123         try:
124             time.sleep(10)
125         except:  # pylint: disable=bare-except
126             # Ignore
127             pass
128
129
130 def main(command_line):
131     """Drives the main operation of the inferior test program.
132
133     @param command_line the command line options to process.
134
135     @return the exit value (program return code) for the process.
136     """
137     options = parse_args(command_line)
138     handle_ignore_signals(options, options.ignore_signals)
139     handle_launch_children(options)
140     handle_sleep(options, options.sleep_seconds)
141     handle_never_return(options)
142
143     return options.return_code
144
145 if __name__ == "__main__":
146     sys.exit(main(sys.argv[1:]))