diff --git a/common.py b/common.py index 7a46f0d..f9cb96d 100644 --- a/common.py +++ b/common.py @@ -7,6 +7,7 @@ import re import subprocess import os import shlex +import signal import stat import sys @@ -144,6 +145,43 @@ def print_cmd(cmd, cmd_file=None): st = os.stat(cmd_file) os.chmod(cmd_file, st.st_mode | stat.S_IXUSR) +def run_cmd(cmd, cmd_file=None, out_file=None, **kwargs): + """ + Run a command. Write the command to stdout before running it. + + Wait until the command finishes execution. + + If: + + - cmd_file is not None, write the command to the given file + - out_file is not None, write the stdout and stderr of the command to the given file + """ + if out_file: + stdout=subprocess.PIPE + stderr=subprocess.STDOUT + else: + stdout=None + stderr=None + print_cmd(cmd, cmd_file) + # Otherwise Ctrl + C gives: + # - ugly Python stack trace for gem5 (QEMU takes over terminal and is fine). + # - kills Python, and that then kills GDB: https://stackoverflow.com/questions/19807134/does-python-always-raise-an-exception-if-you-do-ctrlc-when-a-subprocess-is-exec + signal.signal(signal.SIGINT, signal.SIG_IGN) + # https://stackoverflow.com/questions/15535240/python-popen-write-to-stdout-and-log-file-simultaneously/52090802#52090802 + with subprocess.Popen(cmd, stdout=stdout, stderr=stderr, **kwargs) as proc: + if out_file is not None: + with open(out_file, 'bw') as logfile: + while True: + byte = proc.stdout.read(1) + if byte: + sys.stdout.buffer.write(byte) + sys.stdout.flush() + logfile.write(byte) + else: + break + signal.signal(signal.SIGINT, signal.SIG_DFL) + return proc.returncode + def setup(parser, **extra_args): """ Parse the command line arguments, and setup several variables based on them. @@ -208,7 +246,7 @@ def setup(parser, **extra_args): this.executable = this.qemu_executable this.run_dir = this.qemu_run_dir this.termout_file = this.qemu_termout_file - this.cmd_file = os.path.join(this.run_dir, 'cmd.sh') + this.run_cmd_file = os.path.join(this.run_dir, 'cmd.sh') if args.arch == 'arm': this.linux_image = os.path.join('arch', 'arm', 'boot', 'zImage') elif args.arch == 'aarch64': diff --git a/gem5-shell b/gem5-shell index 72d8958..1abe48a 100755 --- a/gem5-shell +++ b/gem5-shell @@ -10,4 +10,4 @@ parser = common.get_argparse( argparse_args={'description':'Connect a terminal to a running gem5 instance'} ) args = common.setup(parser) -sys.exit(subprocess.Popen([str(common.gem5_m5term), 'localhost', str(common.gem5_telnet_port)]).wait()) +sys.exit(common.run_cmd([str(common.gem5_m5term), 'localhost', str(common.gem5_telnet_port)])) diff --git a/run b/run index 5f03625..cb21f05 100755 --- a/run +++ b/run @@ -2,7 +2,6 @@ import os import shlex -import signal import subprocess import sys import re @@ -375,30 +374,12 @@ if args.tmux: ]) cmd += extra_emulator_args -do_tee = not debug_vm -if do_tee: - stdout=subprocess.PIPE - stderr=subprocess.STDOUT +if debug_vm: + out_file = None else: - stdout=None - stderr=None -common.print_cmd(cmd, common.cmd_file) -# Otherwise Ctrl + C gives an ugly Python stack trace for gem5 (QEMU takes over terminal and is fine). -signal.signal(signal.SIGINT, signal.SIG_IGN) -# https://stackoverflow.com/questions/15535240/python-popen-write-to-stdout-and-log-file-simultaneously/52090802#52090802 -with subprocess.Popen(cmd, stdout=stdout, stderr=stderr, env=env) as proc: - if do_tee: - with open(common.termout_file, 'bw') as logfile: - while True: - byte = proc.stdout.read(1) - if byte: - sys.stdout.buffer.write(byte) - sys.stdout.flush() - logfile.write(byte) - else: - break -signal.signal(signal.SIGINT, signal.SIG_DFL) -if proc.returncode != 0: + out_file = common.termout_file +returncode = common.run_cmd(cmd, cmd_file=common.run_cmd_file, out_file=out_file, env=env) +if returncode != 0: common.error('simulator exited with status != 0') # Check if guest panicked. if args.gem5: diff --git a/rungdb b/rungdb index 982d6dc..3343834 100755 --- a/rungdb +++ b/rungdb @@ -79,13 +79,4 @@ if not args.no_continue: # which gets put on the kernel build root when python debugging scripts are enabled. cmd.extend(['-ex', 'continue'] + lx_symbols) cmd.extend(after) -common.print_cmd(cmd) - -# TODO eeval -# "${common.root_dir}/eeval" "$cmd $after" "${common.run_dir}/rungdb.sh" - -# Required, otherwise Ctrl + C kills Python and that kills GDB. -# https://stackoverflow.com/questions/19807134/does-python-always-raise-an-exception-if-you-do-ctrlc-when-a-subprocess-is-exec -signal.signal(signal.SIGINT, lambda *args: None) - -sys.exit(subprocess.Popen(cmd, cwd=common.linux_variant_dir).wait()) +sys.exit(common.run_cmd(cmd, cmd_file=os.path.join(common.run_dir, 'rungdb.sh'), cwd=common.linux_variant_dir))