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.
This commit is contained in:
Tom Tromey 2023-05-09 14:33:42 -06:00
parent 3eb64586f0
commit fc2d72afc0
3 changed files with 41 additions and 16 deletions

View file

@ -13,21 +13,40 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
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}

View file

@ -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]}

View file

@ -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