diff options
-rw-r--r-- | debugger.c | 53 |
1 files changed, 41 insertions, 12 deletions
@@ -192,13 +192,37 @@ static void capture_state(struct process *proc) { } } +static char thread_state(struct thread *th) { + char statpath[32], stat[512]; + snprintf(statpath, sizeof(statpath), "/proc/%li/stat", (long)th->id); + + FILE *f = fopen(statpath, "r"); + if (f) { + fread(stat, 1, sizeof(stat), f); + fclose(f); + + char *c = strchr(stat, ' '); + c = strchr(c+1, ' ') + 1; + return *c; + } + + return 0; +} + static int wait_thread(struct thread *th); static void interrupt_all_threads(struct process *proc) { struct list *threads = &proc->threads; for (struct thread *th = threads->head; th != threads->end; th = th->next) { if (!th->stopped) { ptrace(PTRACE_INTERRUPT, th->id, NULL, NULL); - while (!wait_thread(th)) {} + + char state; + do { + state = thread_state(th); + } while (state != 't' && state != 'D'); + + wait_thread(th); + //if (STOP_ALL_ON_EVENT) { // th->cont = 0; // th->shouldcont = 0; @@ -211,13 +235,20 @@ static void continue_all_threads(struct process *proc) { struct list *threads = &proc->threads; for (struct thread *th = threads->head; th != threads->end; th = th->next) { if (th->id > 0) { - ptrace(PTRACE_CONT, th->id, NULL, th->signal); - th->stopped = 0; - th->signal = 0; - th->donext = 0; - th->doing = PTRACE_CONT; - strcpy(th->status, "RUNNING"); - th->clearstates = 1; + char state; + do { + wait_thread(th); + + ptrace(PTRACE_CONT, th->id, NULL, th->signal); + th->stopped = 0; + th->signal = 0; + th->donext = 0; + th->doing = PTRACE_CONT; + strcpy(th->status, "RUNNING"); + th->clearstates = 1; + + state = thread_state(th); + } while (state == 't'); } } } @@ -435,12 +466,10 @@ void dbg_detach(struct process *proc) { /* ptrace requires that threads be stopped before calling PTRACE_DETACH. * In some cases, a blocked thread can possibly have a pending trap which * would crash the process if encountered after ptracing. We cycle an extra - * continue/interrupt to consume this trap event ourselves before detaching. - * Threads must actually get scheduled for this to be effective, which is - * the reason for the usleep. A better approach is welcome here. */ + * continue/interrupt to consume this trap event ourselves before + * detaching. */ interrupt_all_threads(proc); continue_all_threads(proc); - usleep(SCHEDULER_DELAY); interrupt_all_threads(proc); /* Supplement to PTRACE_O_EXITKILL */ |