]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
DAP: Handle "stepOut" request in outermost frame
authorJohan Sternerup <johan.sternerup@gmail.com>
Sat, 1 Jun 2024 16:16:32 +0000 (18:16 +0200)
committerTom Tromey <tromey@adacore.com>
Thu, 6 Jun 2024 16:25:19 +0000 (10:25 -0600)
Previously a "stepOut" request when in the outermost frame would result
in a sucessful response even though gdb internally would reject the
associated "finish" request, which means no stoppedEvent would ever be
sent back to the client. Thus the client would believe the inferior was
still running and as a consequence reject subsequent "next" and "stepIn"
requests from the user.

The solution is to execute the underlying finish command as a background
command, i.e. `finish &`. If we're in the outermost frame an exception
will be raised immediately, which we can now capture and report back to
the client as success=False so then the absence of a `stopped` event is
no longer a problem.

We also make use of the `defer_stop_event` option to prevent a stop
event from reaching the client until the response has been sent.

Approved-By: Tom Tromey <tom@tromey.com>
gdb/python/lib/gdb/dap/next.py
gdb/testsuite/gdb.dap/step-out.exp

index 1dc1d6dd74d192b45b65077750c06e1bd3977cb2..7e06b1b79dc47e405dabede395ab3b77cf6f4584 100644 (file)
@@ -73,10 +73,10 @@ def step_in(
     exec_and_expect_stop(cmd)
 
 
-@request("stepOut", response=False)
+@request("stepOut", defer_stop_events=True)
 def step_out(*, threadId: int, singleThread: bool = False, **args):
     _handle_thread_step(threadId, singleThread, True)
-    exec_and_expect_stop("finish")
+    exec_and_expect_stop("finish &", propagate_exception=True)
 
 
 # This is a server-side request because it is funny: it wants to
index 757f4ebdaca989d4055e53b576f1457e6b724b1a..31c50bb81ec522b8f189cace6b795283be7b6b7a 100644 (file)
@@ -79,4 +79,15 @@ gdb_assert {[dict get $varlist variablesReference] > 0} \
 gdb_assert {[dict get $varlist name] == "(return)"} \
     "variable is return value"
 
+set response_and_events [dap_request_and_response stepOut {o threadId [i 1]}]
+set response [lindex $response_and_events 0]
+if {[dict get $response success] == "true"} {
+    fail "stepOut from outermost frame should not succeed"
+} else {
+    pass "stepOut from outermost frame failed like it should"
+}
+
+dap_check_request_and_response "still stopped and may request backtrace" \
+    stackTrace {o threadId [i 1]}
+
 dap_shutdown