Skip to content

Commit c39a540

Browse files
author
Roman Rashchupkin
committed
Don't fail if some threads exit during attach.
1 parent 9752ec3 commit c39a540

File tree

2 files changed

+40
-25
lines changed

2 files changed

+40
-25
lines changed

src/kpatch_process.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
#include <sys/stat.h>
1313
#include <sys/sysmacros.h>
1414

15+
#include <sys/syscall.h>
16+
#include <sys/types.h>
17+
#include <sys/wait.h>
18+
#include <sys/ptrace.h>
19+
1520
#include <gelf.h>
1621
#include <libunwind.h>
1722
#include <libunwind-ptrace.h>
@@ -641,6 +646,7 @@ kpatch_process_attach(kpatch_process_t *proc)
641646
{
642647
int *pids = NULL, ret;
643648
size_t i, npids = 0, alloc = 0, prevnpids = 0, nattempts;
649+
struct kpatch_ptrace_ctx *pctx;
644650

645651
if (kpatch_process_mem_open(proc, MEM_WRITE) < 0)
646652
return -1;
@@ -653,16 +659,11 @@ kpatch_process_attach(kpatch_process_t *proc)
653659
if (nattempts == 0) {
654660
kpdebug("Found %lu thread(s), attaching...\n", npids);
655661
} else {
656-
/*
657-
* FIXME(pboldin): This is wrong, amount of threads can
658-
* be the same because some new spawned and some old
659-
* died
660-
*/
661662
if (prevnpids == npids)
662663
break;
663664

664665
kpdebug("Found %lu new thread(s), attaching...\n",
665-
prevnpids - npids);
666+
npids - prevnpids);
666667
}
667668

668669
if (proc->is_just_started && npids > 1 && proc->send_fd == -1) {
@@ -683,20 +684,24 @@ kpatch_process_attach(kpatch_process_t *proc)
683684
goto detach;
684685
}
685686

686-
prevnpids = npids;
687+
prevnpids = 0;
688+
list_for_each_entry(pctx, &proc->ptrace.pctxs, list)
689+
prevnpids++;
687690
}
688691

689692
if (nattempts == max_attach_attempts) {
690693
kperr("unable to catch up with process, bailing\n");
691694
goto detach;
692695
}
693696

694-
kpinfo("attached to %lu thread(s): %d", npids, pids[0]);
695-
for (i = 1; i < npids; i++)
696-
kpinfo(", %d", pids[i]);
697-
kpinfo("\n");
698-
699-
free(pids);
697+
kpinfo("Attached to %lu thread(s):", npids);
698+
list_for_each_entry(pctx, &proc->ptrace.pctxs, list) {
699+
kpinfo(" %d", pctx->pid);
700+
if (pctx->list.next != &proc->ptrace.pctxs)
701+
kpinfo(",");
702+
else
703+
kpinfo("\n");
704+
}
700705

701706
if (proc->ptrace.unwd == NULL) {
702707
proc->ptrace.unwd = unw_create_addr_space(&_UPT_accessors,
@@ -707,6 +712,7 @@ kpatch_process_attach(kpatch_process_t *proc)
707712
}
708713
}
709714

715+
free(pids);
710716
return 0;
711717

712718
detach:

src/kpatch_ptrace.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,28 +1126,30 @@ int kpatch_ptrace_attach_thread(kpatch_process_t *proc,
11261126
int status;
11271127
struct kpatch_ptrace_ctx *pctx;
11281128

1129-
pctx = kpatch_ptrace_ctx_alloc(proc);
1130-
if (pctx == NULL) {
1131-
kperr("Can't alloc kpatch_ptrace_ctx");
1132-
return -1;
1133-
}
1134-
1135-
pctx->pid = tid;
1136-
kpdebug("Attaching to %d...", pctx->pid);
1137-
1138-
ret = ptrace(PTRACE_ATTACH, pctx->pid, NULL, NULL);
1129+
ret = ptrace(PTRACE_ATTACH, tid, NULL, NULL);
11391130
if (ret < 0) {
1140-
kplogerror("can't attach to %d\n", pctx->pid);
1131+
if (errno == ESRCH) {
1132+
kpinfo("Thread %d exited before attach.\n", tid);
1133+
return 0;
1134+
}
1135+
kplogerror("can't attach to %d\n", tid);
11411136
return -1;
11421137
}
11431138

1139+
kpdebug("Attaching to %d...", tid);
1140+
11441141
do {
11451142
ret = waitpid(tid, &status, __WALL);
11461143
if (ret < 0) {
11471144
kplogerror("can't wait for thread\n");
11481145
return -1;
11491146
}
11501147

1148+
if (WIFEXITED(status)) {
1149+
kpinfo("Thread %d exited during attach.\n", tid);
1150+
return 0;
1151+
}
1152+
11511153
/* We are expecting SIGSTOP */
11521154
if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP)
11531155
break;
@@ -1162,14 +1164,21 @@ int kpatch_ptrace_attach_thread(kpatch_process_t *proc,
11621164
status = WTERMSIG(status);
11631165

11641166

1165-
ret = ptrace(PTRACE_CONT, pctx->pid, NULL,
1167+
ret = ptrace(PTRACE_CONT, tid, NULL,
11661168
(void *)(uintptr_t)status);
11671169
if (ret < 0) {
11681170
kplogerror("can't cont tracee\n");
11691171
return -1;
11701172
}
11711173
} while (1);
11721174

1175+
pctx = kpatch_ptrace_ctx_alloc(proc);
1176+
if (pctx == NULL) {
1177+
kperr("Can't alloc kpatch_ptrace_ctx");
1178+
return -1;
1179+
}
1180+
1181+
pctx->pid = tid;
11731182
pctx->running = 0;
11741183

11751184
kpdebug("OK\n");

0 commit comments

Comments
 (0)