From 0b32d225818f04390a576b1a68ef1a3060fdeb34 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 12 Dec 2023 10:09:55 -0700 Subject: [PATCH] Avoid exception from attach in DAP MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit I noticed that the DAP attach test case (and similarly remoted-dap.exp) had a rogue exception stack trace in the log. It turns out that an attach will generate a stop that does not have a reason. This patch fixes the problem in the _on_stop event listener by making it a bit more careful when examining the event reason. It also adds some machinery so that attach stops can be suppressed, which I think is the right thing to do. Reviewed-By: Kévin Le Gouguec --- gdb/python/lib/gdb/dap/events.py | 33 ++++++++++++++++++++++++++++----- gdb/python/lib/gdb/dap/launch.py | 3 ++- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/gdb/python/lib/gdb/dap/events.py b/gdb/python/lib/gdb/dap/events.py index cbefe90..311bdc3 100644 --- a/gdb/python/lib/gdb/dap/events.py +++ b/gdb/python/lib/gdb/dap/events.py @@ -147,6 +147,16 @@ def _cont(event): ) +_suppress_stop = False + + +@in_gdb_thread +def suppress_stop(): + """Indicate that the next stop should not emit an event.""" + global _suppress_stop + _suppress_stop = True + + _expected_pause = False @@ -198,6 +208,13 @@ stop_reason_map = { def _on_stop(event): global inferior_running inferior_running = False + + global _suppress_stop + if _suppress_stop: + _suppress_stop = False + log("suppressing stop in _on_stop") + return + log("entering _on_stop: " + repr(event)) log(" details: " + repr(event.details)) obj = { @@ -206,17 +223,23 @@ def _on_stop(event): } if isinstance(event, gdb.BreakpointEvent): obj["hitBreakpointIds"] = [x.number for x in event.breakpoints] - global stop_reason_map - reason = event.details["reason"] global _expected_pause - if ( + # Some stop events still do not emit details. For example, + # 'attach' causes a reason-less stop. + if "reason" not in event.details: + # This can only really happen via a "repl" evaluation of + # something like "attach". In this case just emit a generic + # stop. + obj["reason"] = "stopped" + elif ( _expected_pause - and reason == "signal-received" + and event.details["reason"] == "signal-received" and event.details["signal-name"] in ("SIGINT", "SIGSTOP") ): obj["reason"] = "pause" else: - obj["reason"] = stop_reason_map[reason] + global stop_reason_map + obj["reason"] = stop_reason_map[event.details["reason"]] _expected_pause = False send_event("stopped", obj) diff --git a/gdb/python/lib/gdb/dap/launch.py b/gdb/python/lib/gdb/dap/launch.py index 5f95bfd..5ddf5e6 100644 --- a/gdb/python/lib/gdb/dap/launch.py +++ b/gdb/python/lib/gdb/dap/launch.py @@ -18,7 +18,7 @@ import gdb # These are deprecated in 3.9, but required in older versions. from typing import Mapping, Optional, Sequence -from .events import exec_and_expect_stop, expect_process +from .events import exec_and_expect_stop, expect_process, suppress_stop from .server import request, capability from .startup import exec_and_log, DAPException @@ -88,6 +88,7 @@ def attach( else: raise DAPException("attach requires either 'pid' or 'target'") expect_process("attach") + suppress_stop() exec_and_log(cmd) -- 2.7.4