我在Linux中围绕ptrace
进行了一些实验,不知道为什么下面的代码不起作用。这个问题与calling ptrace inside a ptraced Linux process有关。
目标如下:分叉该进程,然后父进程P
和子进程C
彼此运行ptrace(PTRACE_SEIZE, ...)
,以便从int3
P
(分别是C
)可以捕获C
(分别来自P
)。
下面的代码试图实现这一点,但是当父过程P
在int3
函数中的sleep(1)
之后引发do_loop
时,它将挂起:我相信孩子进程C
被while循环中的waitpid
阻塞。
是否可以修补代码以达到预期的行为?
#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#define DO_INT3(who) do { \
printf("%s: raising an int3\n", who); \
__asm__("int $3"); \
printf("%s: raised int3\n", who); \
} while(0);
void do_loop(char *who, pid_t pid) {
int status;
printf("%s: waiting...\n", who);
while( waitpid(pid, &status, 0) != -1) {
switch (WSTOPSIG(status)) {
case SIGTRAP: printf("%s: **** CATCHED SIGTRAP ****\n", who); break;
case SIGSTOP: printf("%s: **** CATCHED SIGSTOP ****\n", who); break;
default: printf("%s: **** CATCHED EVENT %d ****\n", who, WSTOPSIG(status));
}
/* Continue the execution*/
ptrace(PTRACE_CONT, pid, NULL, NULL);
/* Next action */
sleep(1); /* wait for child to attach */
DO_INT3(who);
} /*while*/
}
int main() {
pid_t pid = fork();
if (pid) {
printf("parent: child pid is %d\n", pid);
ptrace(PTRACE_SEIZE, pid, NULL, NULL);
printf("parent: attached to child\n");
do_loop("parent", pid);
} else {
pid_t parent = getppid();
printf("child: parent pid is %d\n", parent);
sleep(1); /* wait for parent to attach */
DO_INT3("child");
ptrace(PTRACE_SEIZE, parent, NULL, NULL);
printf("child: attached to parent\n");
do_loop("child", parent);
}
return 0;
}