ClangBuiltLinux / boot-utils

Collection of files for booting Linux kernels
26 stars 7 forks source link

issue with ctrl+c in -g mode #86

Closed nickdesaulniers closed 1 year ago

nickdesaulniers commented 1 year ago

if I use ctrl+c in gdb mode, I get a crash:

(gdb) c
Continuing.
^Cqemu-system-ppc: terminating on signal 2
[Inferior 1 (process 1) exited normally]
(gdb) Traceback (most recent call last):
  File "/android1/boot-utils/boot-qemu.py", line 807, in <module>
    launch_qemu(config)
  File "/android1/boot-utils/boot-qemu.py", line 773, in launch_qemu
    subprocess.run(gdb_cmd, check=False)
  File "/usr/lib/python3.10/subprocess.py", line 505, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
  File "/usr/lib/python3.10/subprocess.py", line 1146, in communicate
    self.wait()
  File "/usr/lib/python3.10/subprocess.py", line 1209, in wait
    return self._wait(timeout=timeout)
  File "/usr/lib/python3.10/subprocess.py", line 1943, in _wait
    (pid, sts) = self._try_wait(0)
  File "/usr/lib/python3.10/subprocess.py", line 1901, in _try_wait
    (pid, sts) = os.waitpid(self.pid, wait_flags)
KeyboardInterrupt

but if I ps -ef | grep gdb then send that process a SIGINT kill -SIGINT <pid> I get the expected output:

(gdb) c
Continuing.

Program received signal SIGINT, Interrupt.
0xfff0b37c in ?? ()

This is important because it's common to halt the machine to grab a back trace via ctrl+c then bt in gdb.

nathanchance commented 1 year ago

Ugh... I am not really sure how to fix this. We can intercept Ctrl-C via the KeyboardInterrupt exception and pass it along to gdb via send_signal(signal.SIGINT), keeping control of the script, but QEMU gets killed by gdb when it receives SIGINT it seems. I found https://bugzilla.kernel.org/show_bug.cgi?id=9039 from https://stackoverflow.com/questions/30925198/how-to-pass-sigint-to-child-process-with-python-subprocess-popen-using-shell, which makes it seem like this is expected behavior...

In the meantime, we could either suggest using kill -2 or just stop running gdb altogether, instead printing the gdb command that should be run in a separate terminal.

nickdesaulniers commented 1 year ago

but QEMU gets killed by gdb when it receives SIGINT it seems

That's not what happened when I ran kill -SIGINT <pid of gdb> above; I was able to run bt in gdb after.

nathanchance commented 1 year ago

Sorry I did not make myself clear enough. That is what happened when I was able to intercept Ctrl-C from Python and pass it to the gdb process. I tried something like this:

    if gdb:
        utils.check_cmd(gdb_bin)
        gdb_cmd = [
            gdb_bin,
            kernel_location.joinpath('vmlinux'),
            '-ex', 'target remote :1234'
        ]  # yapf: disable

        while True:
            utils.check_cmd("lsof")
            lsof = subprocess.run(["lsof", "-i:1234"],
                                  stdout=subprocess.DEVNULL,
                                  stderr=subprocess.DEVNULL,
                                  check=False)
            if lsof.returncode == 0:
                utils.die("Port 1234 is already in use, is QEMU running?")

            utils.green("Starting QEMU with GDB connection on port 1234...")
            qemu_process = subprocess.Popen(qemu_cmd + ['-s', '-S'])

            utils.green("Starting GDB...")
            gdb_process = subprocess.Popen(gdb_cmd)
            while True:
                try:
                    gdb_process.wait()
                except KeyboardInterrupt:
                    gdb_process.send_signal(signal.SIGINT)
                else:
                    break

            utils.red("Killing QEMU...")
            qemu_process.kill()

            answer = input("Re-run QEMU + gdb? [y/n] ")
            if answer.lower() == "n":
                break