From fc2d72afc0516e397dc0d7edb75930efa3697a2c Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Tue, 9 May 2023 14:33:42 -0600 Subject: [PATCH] Add singleThread support to some DAP requests A few DAP requests support a "singleThread" parameter, which is somewhat similar to scheduler-locking. This patch implements support for this. --- gdb/python/lib/gdb/dap/next.py | 45 +++++++++++++++++------ gdb/testsuite/gdb.dap/basic-dap.exp | 9 +++-- gdb/testsuite/gdb.dap/catch-exception.exp | 3 +- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/gdb/python/lib/gdb/dap/next.py b/gdb/python/lib/gdb/dap/next.py index 232b1529fe5..290b9b855ba 100644 --- a/gdb/python/lib/gdb/dap/next.py +++ b/gdb/python/lib/gdb/dap/next.py @@ -13,21 +13,40 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import gdb + from .events import StopKinds, ExecutionInvoker from .server import capability, request -from .startup import send_gdb +from .startup import in_gdb_thread, send_gdb, send_gdb_with_response from .state import set_thread -# Helper function to set the current thread. -def _handle_thread_step(threadId): +# Helper function to set the current thread and the scheduler-locking +# mode. Returns True if scheduler-locking was successfully set to +# 'on', False in all other cases, including error. +@in_gdb_thread +def _handle_thread_step(thread_id, single_thread): # Ensure we're going to step the correct thread. - send_gdb(lambda: set_thread(threadId)) + set_thread(thread_id) + if single_thread: + result = True + arg = "on" + else: + result = False + arg = "off" + try: + # This can fail, depending on the target, so catch the error + # and report to our caller. We can't use exec_and_log because + # that does not propagate exceptions. + gdb.execute("set scheduler-locking " + arg, from_tty=True, to_string=True) + except gdb.error: + result = False + return result @request("next") -def next(*, threadId, granularity="statement", **args): - _handle_thread_step(threadId) +def next(*, threadId, singleThread=False, granularity="statement", **args): + send_gdb(lambda: _handle_thread_step(threadId, singleThread)) cmd = "next" if granularity == "instruction": cmd += "i" @@ -35,9 +54,10 @@ def next(*, threadId, granularity="statement", **args): @capability("supportsSteppingGranularity") +@capability("supportsSingleThreadExecutionRequests") @request("stepIn") -def stepIn(*, threadId, granularity="statement", **args): - _handle_thread_step(threadId) +def stepIn(*, threadId, singleThread=False, granularity="statement", **args): + send_gdb(lambda: _handle_thread_step(threadId, singleThread)) cmd = "step" if granularity == "instruction": cmd += "i" @@ -45,12 +65,13 @@ def stepIn(*, threadId, granularity="statement", **args): @request("stepOut") -def step_out(*, threadId): - _handle_thread_step(threadId) +def step_out(*, threadId, singleThread=False): + send_gdb(lambda: _handle_thread_step(threadId, singleThread)) send_gdb(ExecutionInvoker("finish", StopKinds.STEP)) @request("continue") -def continue_request(**args): +def continue_request(*, threadId, singleThread=False, **args): + locked = send_gdb_with_response(lambda: _handle_thread_step(threadId, singleThread)) send_gdb(ExecutionInvoker("continue", None)) - return {"allThreadsContinued": True} + return {"allThreadsContinued": not locked} diff --git a/gdb/testsuite/gdb.dap/basic-dap.exp b/gdb/testsuite/gdb.dap/basic-dap.exp index d4dbdac70ff..ce739875404 100644 --- a/gdb/testsuite/gdb.dap/basic-dap.exp +++ b/gdb/testsuite/gdb.dap/basic-dap.exp @@ -136,15 +136,18 @@ set obj [dap_check_request_and_response "evaluate global second time" \ dap_match_values "global value after step" [lindex $obj 0] \ "body result" 24 -dap_check_request_and_response "continue to address" continue +dap_check_request_and_response "continue to address" continue \ + {o threadId [i 1]} dap_wait_for_event_and_check "stopped at address breakpoint" stopped \ "body reason" breakpoint \ "body hitBreakpointIds" $insn_bpno -dap_check_request_and_response "continue to line" continue +dap_check_request_and_response "continue to line" continue \ + {o threadId [i 1]} dap_wait_for_event_and_check "stopped at line breakpoint" stopped \ "body reason" breakpoint \ - "body hitBreakpointIds" $line_bpno + "body hitBreakpointIds" $line_bpno \ + "body allThreadsStopped" true dap_check_request_and_response "return from function" stepOut \ {o threadId [i 1]} diff --git a/gdb/testsuite/gdb.dap/catch-exception.exp b/gdb/testsuite/gdb.dap/catch-exception.exp index 6bfeb3ed87e..7f2e750b32e 100644 --- a/gdb/testsuite/gdb.dap/catch-exception.exp +++ b/gdb/testsuite/gdb.dap/catch-exception.exp @@ -57,7 +57,8 @@ dap_wait_for_event_and_check "stopped at first raise" stopped \ "body reason" breakpoint \ "body hitBreakpointIds" 2 -dap_check_request_and_response "continue to assert" continue +dap_check_request_and_response "continue to assert" continue \ + {o threadId [i 1]} dap_wait_for_event_and_check "stopped at assert" stopped \ "body reason" breakpoint \ "body hitBreakpointIds" 1 -- 2.30.2