From ecac42af735c3fa6abe49ec7cf9ebcd34096b2ac Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 3 Sep 2025 09:26:25 -0600 Subject: [PATCH] Always propagate exceptions in DAP This changes the DAP exec_and_log function to always transform an exception into a DAPException and propagate it. As the bug points out, we haven't always wrapped calls when appropriate. I think it's better to cause the request to fail by default; if any spot truly needs to ignore errors, that is readily done at the point of call. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=33346 --- gdb/python/lib/gdb/dap/events.py | 4 ++-- gdb/python/lib/gdb/dap/next.py | 2 +- gdb/python/lib/gdb/dap/startup.py | 10 ++++----- gdb/testsuite/gdb.dap/attach-fail.exp | 32 +++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 gdb/testsuite/gdb.dap/attach-fail.exp diff --git a/gdb/python/lib/gdb/dap/events.py b/gdb/python/lib/gdb/dap/events.py index e8f26550a16..778acc57eb0 100644 --- a/gdb/python/lib/gdb/dap/events.py +++ b/gdb/python/lib/gdb/dap/events.py @@ -161,7 +161,7 @@ _expected_pause = False @in_gdb_thread -def exec_and_expect_stop(cmd, expected_pause=False, propagate_exception=False): +def exec_and_expect_stop(cmd, expected_pause=False): """A wrapper for exec_and_log that sets the continue-suppression flag. When EXPECTED_PAUSE is True, a stop that looks like a pause (e.g., @@ -174,7 +174,7 @@ def exec_and_expect_stop(cmd, expected_pause=False, propagate_exception=False): # continuing. _suppress_cont = not expected_pause # FIXME if the call fails should we clear _suppress_cont? - exec_and_log(cmd, propagate_exception) + exec_and_log(cmd) # Map from gdb stop reasons to DAP stop reasons. Some of these can't diff --git a/gdb/python/lib/gdb/dap/next.py b/gdb/python/lib/gdb/dap/next.py index 898fff1936a..a0fa18eae1d 100644 --- a/gdb/python/lib/gdb/dap/next.py +++ b/gdb/python/lib/gdb/dap/next.py @@ -76,7 +76,7 @@ def step_in( @request("stepOut") def step_out(*, threadId: int, singleThread: bool = False, **args): _handle_thread_step(threadId, singleThread, True) - exec_and_expect_stop("finish &", propagate_exception=True) + exec_and_expect_stop("finish &") @request("continue") diff --git a/gdb/python/lib/gdb/dap/startup.py b/gdb/python/lib/gdb/dap/startup.py index ab3e8fd32a5..0c95ada80ac 100644 --- a/gdb/python/lib/gdb/dap/startup.py +++ b/gdb/python/lib/gdb/dap/startup.py @@ -204,7 +204,7 @@ def log_stack(level=LogLevel.DEFAULT): @in_gdb_thread -def exec_and_log(cmd, propagate_exception=False): +def exec_and_log(cmd): """Execute the gdb command CMD. If logging is enabled, log the command and its output.""" log("+++ " + cmd) @@ -213,10 +213,10 @@ def exec_and_log(cmd, propagate_exception=False): if output != "": log(">>> " + output) except gdb.error as e: - if propagate_exception: - raise DAPException(str(e)) from e - else: - log_stack() + # Don't normally want to see this, as it interferes with the + # test suite. + log_stack(LogLevel.FULL) + raise DAPException(str(e)) from e @in_gdb_thread diff --git a/gdb/testsuite/gdb.dap/attach-fail.exp b/gdb/testsuite/gdb.dap/attach-fail.exp new file mode 100644 index 00000000000..8992f629f66 --- /dev/null +++ b/gdb/testsuite/gdb.dap/attach-fail.exp @@ -0,0 +1,32 @@ +# Copyright 2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Test "attach" failure in DAP. + +require can_spawn_for_attach allow_dap_tests + +load_lib dap-support.exp + +# Passing an empty remote name here will guarantee a failure without +# trying to find a real remote. +set id [dap_target_remote {""}] + +dap_check_request_and_response "configurationDone" configurationDone + +set resp [lindex [dap_read_response attach $id] 0] +gdb_assert {[dict get $resp success] == "false"} \ + "attach failed" + +dap_shutdown -- 2.47.3