在我的项目中,我需要附加到进程,恢复它们,然后再使用ptrace.但是,分离失败了errno=ESRCH (No such process).
如果我没有恢复进程,则分离工作正常PTRACE_CONT,但在这种情况下,进程停止/无响应,这在我的项目中是不可接受的.在Arch和Ubuntu 12.04 LTS上测试,结果相同.
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
pid_t pid = 21000;
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) {
perror("PTRACE_ATTACH");
return 1;
}
printf("attached\n");
waitpid(pid, NULL, WUNTRACED);
if (ptrace(PTRACE_CONT, pid, NULL, NULL) == -1) {
perror("PTRACE_CONT");
return 1;
}
printf("continued\n");
if (ptrace(PTRACE_DETACH, pid, NULL, NULL) == -1) {
perror("PTRACE_DETACH");
return 1;
}
printf("detached\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
attached
continued
PTRACE_DETACH: No such process
Run Code Online (Sandbox Code Playgroud)
根据ptrace手册页,应该在尝试从中删除之前停止该过程:
通过以下方式执行tracee的分离:
ptrace(PTRACE_DETACH,pid,0,sig);
PTRACE_DETACH是一个重启动作; 因此它需要tracee处于ptrace-stop.如果迹线处于信号传递停止状态,则可以注入信号.否则,可以静默忽略sig参数.如果跟踪器在跟踪器想要分离时正在运行,通常的解决方案是发送SIGSTOP(使用tgkill(2),以确保它转到正确的线程),等待tracee在信号传递停止时停止对于SIGSTOP然后分离它(抑制SIGSTOP注入).设计错误是它可以与并发SIGSTOP竞争.另一个复杂因素是tracee可能会进入其他ptrace-stops并需要重新启动并再次等待,直到看到SIGSTOP.另一个复杂因素是确保tracee尚未被停止,因为没有信号传递发生 - 甚至不是SIGSTOP.
在您的示例代码中,实际上不需要调用ptrace(PTRACE_CONT, ...).你可以脱离这个过程.如果该代码属于更大的代码段,那么您可以使用tgkill()(或者只是kill在您不使用线程时):
ptrace(PTRACE_CONT, ...);
kill(pid, SIGSTOP);
waitpid(pid, NULL, 0);
ptrace(PTRACE_DETACH, ...);
Run Code Online (Sandbox Code Playgroud)