Skip to content

Fix handling of auto_continue for stop hooks #129622

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions lldb/source/Target/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3073,7 +3073,6 @@ bool Target::RunStopHooks() {

bool print_hook_header = (m_stop_hooks.size() != 1);
bool print_thread_header = (num_exe_ctx != 1);
bool auto_continue = false;
bool should_stop = false;
bool requested_continue = false;

Expand All @@ -3087,10 +3086,6 @@ bool Target::RunStopHooks() {
if (!cur_hook_sp->ExecutionContextPasses(exc_ctx))
continue;

// We only consult the auto-continue for a stop hook if it matched the
// specifier.
auto_continue |= cur_hook_sp->GetAutoContinue();

if (print_hook_header && !any_thread_matched) {
StreamString s;
cur_hook_sp->GetDescription(s, eDescriptionLevelBrief);
Expand All @@ -3109,7 +3104,10 @@ bool Target::RunStopHooks() {
auto result = cur_hook_sp->HandleStop(exc_ctx, output_sp);
switch (result) {
case StopHook::StopHookResult::KeepStopped:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the "auto continue" override only apply to KeepStopped or all potential HandleStop() -> StopHookResult return values, or a specific set?
@jimingham

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only KeepStopped. If any thread reports AlreadyContinued, then we aren't doing this negotiation anymore, someone called continue directly. Threads reporting NoPreference shouldn't be consulted here. And RequestContinue means that thread goes along with continuing.
GetAutoContinue is formally different, since that is a stop-hook that's asking to auto-continue regardless of what value it returns from the stop hook callback, but in practice is the same as RequestContinue.

should_stop = true;
if (cur_hook_sp->GetAutoContinue())
requested_continue = true;
else
should_stop = true;
break;
case StopHook::StopHookResult::RequestContinue:
requested_continue = true;
Expand All @@ -3134,10 +3132,9 @@ bool Target::RunStopHooks() {
}
}

// Resume iff:
// 1) At least one hook requested to continue and no hook asked to stop, or
// 2) at least one hook had auto continue on.
if ((requested_continue && !should_stop) || auto_continue) {
// Resume iff at least one hook requested to continue and no hook asked to
// stop.
if (requested_continue && !should_stop) {
Log *log = GetLog(LLDBLog::Process);
Status error = m_process_sp->PrivateResume();
if (error.Success()) {
Expand Down
13 changes: 8 additions & 5 deletions lldb/test/API/commands/target/stop-hooks/TestStopHooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@


class TestStopHooks(TestBase):
# If your test case doesn't stress debug info, then
# set this to true. That way it won't be run once for
# each debug info format.
NO_DEBUG_INFO_TESTCASE = True

def setUp(self):
Expand Down Expand Up @@ -42,12 +39,18 @@ def step_out_test(self):

interp = self.dbg.GetCommandInterpreter()
result = lldb.SBCommandReturnObject()
interp.HandleCommand("target stop-hook add -o 'expr g_var++'", result)
# Add two stop hooks here, one to auto-continue and one not. Make sure
# that we still stop in that case.
interp.HandleCommand("target stop-hook add -G false -o 'expr g_var++'", result)
self.assertTrue(result.Succeeded(), "Set the target stop hook")

interp.HandleCommand("target stop-hook add -G true -o 'expr g_var++'", result)
self.assertTrue(result.Succeeded(), "Set the second target stop hook")

thread.StepOut()
var = target.FindFirstGlobalVariable("g_var")
self.assertTrue(var.IsValid())
self.assertEqual(var.GetValueAsUnsigned(), 1, "Updated g_var")
self.assertEqual(var.GetValueAsUnsigned(), 2, "Updated g_var")

def after_expr_test(self):
interp = self.dbg.GetCommandInterpreter()
Expand Down
Loading