在PTRACE_CONT之后PTRACE_DETACH失败并且errno = ESRCH

时间:2013-12-11 04:07:12

标签: c linux ptrace

在我的项目中,我需要附加到进程,恢复它们,然后使用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;
}

输出:

attached
continued
PTRACE_DETACH: No such process

1 个答案:

答案 0 :(得分:5)

根据ptrace手册页,在尝试从中删除之前应该停止该过程:

  

通过以下方式执行tracee的分离:

     

ptrace(PTRACE_DETACH,pid,0,sig);

     

PTRACE_DETACH是一个重启动作;因此它需要       追踪到了ptrace-stop。如果迹象是信号传递 -       停止,可以注入信号。否则,sig参数可能是       默默地忽略了。       如果跟踪器在跟踪器想要分离时运行,则       通常的解决方案是发送SIGSTOP(使用tgkill(2),以确保它       转到正确的线程),等待tracee停止信号 -       SIGSTOP的交付停止然后分离它(抑制SIGSTOP       注射)。一个设计错误是它可以与并发竞争       SIGSTOPs。另一个复杂因素是,tracee可能会进入其他       ptrace-stops并需要重新启动并再次等待,直到       看到SIGSTOP。另一个复杂因素是确保       tracee尚未停止,因为没有信号传递       它发生的时候 - 甚至不是SIGSTOP。

在您的示例代码中,实际上无需调用ptrace(PTRACE_CONT, ...)。你可以脱离这个过程。如果该代码属于更大的代码段,那么您可以使用tgkill()(如果您不使用线程,则只需kill):

ptrace(PTRACE_CONT, ...);
kill(pid, SIGSTOP);
waitpid(pid, NULL, 0);
ptrace(PTRACE_DETACH, ...);