-
-
Notifications
You must be signed in to change notification settings - Fork 20
Add support for cont on individual threads #93
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
Conversation
@@ -501,6 +501,96 @@ int cont_all_and_set_bps(struct global_state *state, int pid) | |||
return status; | |||
} | |||
|
|||
int prepare_thread_for_run(struct global_state *state, int pid, int tid) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, this function is identical to prepare_for_run
but the operations in the second while are performed for the selected thread and not for all threads. Can we have a function called by both prepare_thread_for_run
and prepare_for_run
to avoid copy-paste of code?
@@ -72,7 +72,8 @@ def terminate(self: Debugger) -> None: | |||
|
|||
def cont(self: Debugger) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea isn't the worst, but it introduces an inconsistency between the continue function and the other functions. Typically, if no thread is specified, the action is applied to threads[0]. However, this isn't the case for continue. We can document this exception, but we need to carefully consider its implications.
You were waiting for this comment, I know...
def cont(self: PtraceInterface) -> None: | ||
"""Continues the execution of the process.""" | ||
|
||
def _prepare_for_cont(self: PtraceInterface) -> None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pydoc?
) | ||
def cont(self: PtraceInterface, thread: ThreadContext | None) -> None: | ||
"""Continues the execution of the process.""" | ||
self._prepare_for_cont() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are setting the signals for every thread, even if we are continuing only once (and therefore delivering just the signal for the continued thread). It’s not the cleanest choice, but theoretically, there shouldn't be any side effects. I suppose.
thread = t | ||
break | ||
|
||
assert thread is not None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.assert...
in the whole file
other = d.threads[2] if d.threads[1] == target else d.threads[1] | ||
|
||
if not do_nothing_target.hit_on(target): | ||
# target.step_until(do_nothing_target.address) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
???
target.cont() | ||
|
||
if not do_nothing_other.hit_on(other): | ||
# other.step_until(do_nothing_other.address) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
???
@@ -1257,7 +1257,7 @@ def __threaded_wait(self: InternalDebugger) -> None: | |||
self.resume_context.resume = True | |||
self.debugging_interface.wait() | |||
if self.resume_context.resume: | |||
self.debugging_interface.cont() | |||
self.debugging_interface.cont(self.resume_context.thread_to_cont) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure that self.resume_context.thread_to_cont
is not always None
at this point? The wait is executed from the queue after the continue, and continue, as its last operation, sets self.resume_context.thread_to_cont = None
.
Some general thoughts I put down before switching my phone to bedtime mode. I grasp the overall concept and don't necessarily disagree with it. However, there are some inconsistencies in the APIs that this decision might introduce. Currently, for any function or attribute accessible within the thread context, if they are invoked from the debugger, they reference However, a question arises regarding other control flow functions. If |
I am closing this PR as it is based on the outdated CFFI system. Please refer to the new PRs (such as #171) for this feature, which uses the new nanobind bindings. |
Just used internally at the moment, I know that the junior developer will have things to say about this so I'm not going all-in.
Applied to
finish()
at the moment, but we could just as easily integrate it withnext()
Note to the junior developer: this code was partially (and painfully) written during a plane flight with no Copilot access, so the quality might be a little lower than usual.