scripts: zephyr_flash_debug: teach runners a client/server abstraction Several debugging scripts run setsid before executing a server process, then run GDB with SIGINT ignored. Relying on setsid is not portable. Add a popen_ignore_int() helper that provides a portable alternative, and provide a generic run_server_and_client() in ZephyrBinaryRunner which uses it to abstract the pattern. Subsequent patches will use this to implement the 'debug' command. Signed-off-by: Marti Bolivar <marti.bolivar@linaro.org>
diff --git a/scripts/support/zephyr_flash_debug.py b/scripts/support/zephyr_flash_debug.py index 2228d18..19c1ae7 100755 --- a/scripts/support/zephyr_flash_debug.py +++ b/scripts/support/zephyr_flash_debug.py
@@ -51,6 +51,25 @@ return subprocess.check_output(cmd) +def popen_ignore_int(cmd, debug): + '''Spawn a child command, ensuring it ignores SIGINT. + + The returned subprocess.Popen object must be manually terminated.''' + cflags = 0 + preexec = None + system = platform.system() + + if system == 'Windows': + cflags |= subprocess.CREATE_NEW_PROCESS_GROUP + elif system in {'Linux', 'Darwin'}: + preexec = os.setsid + + if debug: + print(' '.join(cmd)) + + return subprocess.Popen(cmd, creationflags=cflags, preexec_fn=preexec) + + class ZephyrBinaryRunner(abc.ABC): '''Abstract superclass for binary runners (flashers, debuggers). @@ -140,6 +159,25 @@ In case of an unsupported command, raise a ValueError.''' + def run_server_and_client(self, server, client): + '''Run a server that ignores SIGINT, and a client that handles it. + + This routine portably: + + - creates a Popen object for the `server' command which ignores SIGINT + - runs `client' in a subprocess while temporarily ignoring SIGINT + - cleans up the server after the client exits. + + It's useful to e.g. open a GDB server and client.''' + server_proc = popen_ignore_int(server, self.debug) + previous = signal.signal(signal.SIGINT, signal.SIG_IGN) + try: + check_call(client, self.debug) + finally: + signal.signal(signal.SIGINT, previous) + server_proc.terminate() + server_proc.wait() + DEFAULT_ARC_TCL_PORT = 6333 DEFAULT_ARC_TELNET_PORT = 4444