diff --git a/src/kpatch_process.c b/src/kpatch_process.c index 2f85373..36347a2 100644 --- a/src/kpatch_process.c +++ b/src/kpatch_process.c @@ -12,6 +12,11 @@ #include #include +#include +#include +#include +#include + #include #include #include @@ -641,6 +646,7 @@ kpatch_process_attach(kpatch_process_t *proc) { int *pids = NULL, ret; size_t i, npids = 0, alloc = 0, prevnpids = 0, nattempts; + struct kpatch_ptrace_ctx *pctx; if (kpatch_process_mem_open(proc, MEM_WRITE) < 0) return -1; @@ -653,16 +659,11 @@ kpatch_process_attach(kpatch_process_t *proc) if (nattempts == 0) { kpdebug("Found %lu thread(s), attaching...\n", npids); } else { - /* - * FIXME(pboldin): This is wrong, amount of threads can - * be the same because some new spawned and some old - * died - */ if (prevnpids == npids) break; kpdebug("Found %lu new thread(s), attaching...\n", - prevnpids - npids); + npids - prevnpids); } if (proc->is_just_started && npids > 1 && proc->send_fd == -1) { @@ -683,7 +684,9 @@ kpatch_process_attach(kpatch_process_t *proc) goto detach; } - prevnpids = npids; + prevnpids = 0; + list_for_each_entry(pctx, &proc->ptrace.pctxs, list) + prevnpids++; } if (nattempts == max_attach_attempts) { @@ -691,12 +694,14 @@ kpatch_process_attach(kpatch_process_t *proc) goto detach; } - kpinfo("attached to %lu thread(s): %d", npids, pids[0]); - for (i = 1; i < npids; i++) - kpinfo(", %d", pids[i]); - kpinfo("\n"); - - free(pids); + kpinfo("Attached to %lu thread(s):", npids); + list_for_each_entry(pctx, &proc->ptrace.pctxs, list) { + kpinfo(" %d", pctx->pid); + if (pctx->list.next != &proc->ptrace.pctxs) + kpinfo(","); + else + kpinfo("\n"); + } if (proc->ptrace.unwd == NULL) { proc->ptrace.unwd = unw_create_addr_space(&_UPT_accessors, @@ -707,6 +712,7 @@ kpatch_process_attach(kpatch_process_t *proc) } } + free(pids); return 0; detach: diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c index f91b80e..b7268a6 100644 --- a/src/kpatch_ptrace.c +++ b/src/kpatch_ptrace.c @@ -1126,20 +1126,24 @@ int kpatch_ptrace_attach_thread(kpatch_process_t *proc, int status; struct kpatch_ptrace_ctx *pctx; + ret = ptrace(PTRACE_ATTACH, tid, NULL, NULL); + if (ret < 0) { + if (errno == ESRCH) { + kpinfo("Thread %d exited before attach.\n", tid); + return 0; + } + kplogerror("can't attach to %d\n", tid); + return -1; + } + pctx = kpatch_ptrace_ctx_alloc(proc); if (pctx == NULL) { kperr("Can't alloc kpatch_ptrace_ctx"); return -1; } - pctx->pid = tid; - kpdebug("Attaching to %d...", pctx->pid); - ret = ptrace(PTRACE_ATTACH, pctx->pid, NULL, NULL); - if (ret < 0) { - kplogerror("can't attach to %d\n", pctx->pid); - return -1; - } + kpdebug("Attaching to %d...", pctx->pid); do { ret = waitpid(tid, &status, __WALL); @@ -1148,6 +1152,12 @@ int kpatch_ptrace_attach_thread(kpatch_process_t *proc, return -1; } + if (WIFEXITED(status)) { + kpinfo("Thread %d exited during attach.\n", tid); + kpatch_ptrace_ctx_destroy(pctx); + return 0; + } + /* We are expecting SIGSTOP */ if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) break;