summaryrefslogtreecommitdiffstats
path: root/debugger.c
diff options
context:
space:
mode:
Diffstat (limited to 'debugger.c')
-rw-r--r--debugger.c53
1 files changed, 41 insertions, 12 deletions
diff --git a/debugger.c b/debugger.c
index 3435cf4..5981660 100644
--- a/debugger.c
+++ b/debugger.c
@@ -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 */