2 """Inferior program used by process control tests."""
4 from __future__ import print_function
14 def parse_args(command_line):
15 """Parses the command line arguments given to it.
17 @param command_line a list of command line arguments to be parsed.
19 @return the argparse options dictionary.
21 parser = argparse.ArgumentParser()
25 dest="ignore_signals",
30 help="ignore the given signal number (if possible)")
32 "--launch-child-share-handles",
34 help=("launch a child inferior.py that shares stdout/stderr/stdio and "
39 help="run in an infinite loop, never return")
45 help="specify the return code for the inferior upon exit")
52 help="sleep for SECONDS seconds before returning")
54 "--verbose", "-v", action="store_true",
55 help="log verbose operation details to stdout")
56 return parser.parse_args(command_line)
59 def handle_ignore_signals(options, signals):
60 """Ignores any signals provided to it.
62 @param options the command line options parsed by the program.
63 General used to check flags for things like verbosity.
65 @param signals the list of signals to ignore. Can be None or zero-length.
66 Entries should be type int.
71 for signum in signals:
73 print("disabling signum {}".format(signum))
74 signal.signal(signum, signal.SIG_IGN)
77 def handle_sleep(options, sleep_seconds):
78 """Sleeps the number of seconds specified, restarting as needed.
80 @param options the command line options parsed by the program.
81 General used to check flags for things like verbosity.
83 @param sleep_seconds the number of seconds to sleep. If None
84 or <= 0, no sleeping will occur.
86 if sleep_seconds is None:
89 if sleep_seconds <= 0:
92 end_time = datetime.datetime.now() + datetime.timedelta(0, sleep_seconds)
94 print("sleep end time: {}".format(end_time))
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.
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
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"])
117 def handle_never_return(options):
118 if not options.never_return:
125 except: # pylint: disable=bare-except
130 def main(command_line):
131 """Drives the main operation of the inferior test program.
133 @param command_line the command line options to process.
135 @return the exit value (program return code) for the process.
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)
143 return options.return_code
145 if __name__ == "__main__":
146 sys.exit(main(sys.argv[1:]))