summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMalfurious <m@lfurio.us>2023-10-09 16:08:34 -0400
committerMalfurious <m@lfurio.us>2024-04-24 13:31:08 -0400
commitee936125622325a4b33bafe336b44e44a24ce1aa (patch)
tree42d310424c380b17d378e1f1ad0975b1a59de725
parent80a43bdbdeee87605fdbcdd79195edc98b98fd1d (diff)
downloadmisplays-ee936125622325a4b33bafe336b44e44a24ce1aa.tar.gz
misplays-ee936125622325a4b33bafe336b44e44a24ce1aa.zip
Handle PTRACE_EVENT_EXIT to capture a final state snapshot
Also, it is now possible for interrupt_all_threads to fail to stop threads in uninterruptable sleep (eg: the main thread during execve). This may happen in more general cases as well, but it is now common enough in that case to worry about. Signed-off-by: Malfurious <m@lfurio.us>
-rw-r--r--debugger.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/debugger.c b/debugger.c
index 5981660..18f91e1 100644
--- a/debugger.c
+++ b/debugger.c
@@ -16,6 +16,7 @@
static const int PTRACE_OPTIONS =
PTRACE_O_TRACECLONE |
PTRACE_O_TRACEEXEC |
+ PTRACE_O_TRACEEXIT |
PTRACE_O_TRACESYSGOOD;
static const int PTRACE_CHILD_OPTIONS = PTRACE_OPTIONS | PTRACE_O_EXITKILL;
@@ -258,7 +259,7 @@ static void resume_threads(struct process *proc) {
int once = 0;
for (struct thread *th = threads->head; th != threads->end; th = th->next) {
- if (th->doing == PTRACE_SINGLESTEP) {
+ if (th->stopped && th->doing == PTRACE_SINGLESTEP) {
ptrace(PTRACE_SINGLESTEP, th->id, NULL, th->signal);
th->stopped = 0;
th->signal = 0;
@@ -267,7 +268,7 @@ static void resume_threads(struct process *proc) {
}
for (struct thread *th = threads->head; th != threads->end; th = th->next) {
- if (th->doing && th->doing != PTRACE_SINGLESTEP) {
+ if (th->stopped && th->doing && th->doing != PTRACE_SINGLESTEP) {
if (!once) {
usleep(SCHEDULER_DELAY);
once = 1;
@@ -349,6 +350,15 @@ static int wait_thread(struct thread *th) {
th->state = NULL;
return 1;
+ case SIGTRAP | (PTRACE_EVENT_EXIT << 8):
+ th->stopped = 1;
+ th->signal = 0;
+ th->doing = PTRACE_CONT;
+ th->donext = 0;
+ strcpy(th->status, "EXITING");
+ th->state = NULL;
+ return 1;
+
case SIGTRAP | (PTRACE_EVENT_STOP << 8):
th->stopped = 1;
th->signal = 0;