Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux ptrace(ptrace_ME,…)和后续等待出现问题_Linux_Debugging_Wait_Ptrace - Fatal编程技术网

Linux ptrace(ptrace_ME,…)和后续等待出现问题

Linux ptrace(ptrace_ME,…)和后续等待出现问题,linux,debugging,wait,ptrace,Linux,Debugging,Wait,Ptrace,我正在将调试器“pi”(“进程检查器”)移植到Linux和am 处理子对象的fork/exec代码以检查它。我是 按照标准程序(我相信),但等待是悬而未决的。 “hang”是执行工作的过程,“cmd”参数为 要跟踪的二进制文件(a.out)的名称: int Hostfunc::hang(char *cmd){ char *argv[10], *cp; int i; Localproc *p; struct exec exec; struct rlimit

我正在将调试器“pi”(“进程检查器”)移植到Linux和am 处理子对象的fork/exec代码以检查它。我是 按照标准程序(我相信),但等待是悬而未决的。 “hang”是执行工作的过程,“cmd”参数为 要跟踪的二进制文件(a.out)的名称:

int Hostfunc::hang(char *cmd){
    char *argv[10], *cp;
    int i;
    Localproc *p;
    struct exec exec;
    struct rlimit rlim;
    
    i = strlen(cmd);
    if (++i > sizeof(procbuffer)) {
        i = sizeof(procbuffer) - 1;
        procbuffer[i] = 0;
    }
    bcopy(cmd, procbuffer, i);
    argv[0] = cp = procbuffer;
    for(i = 1;;) {
        while(*cp && *cp != ' ')
            cp++;
        if (!*cp) {
            argv[i] = 0;
            break;
        } else {
            *cp++ = 0;
            while (*cp == ' ')
                cp++;
            if (*cp)
                argv[i++] = cp;
        }
    }
    hangpid = fork();
    if (!hangpid){
        int fd, nfiles = 20;
        if(getrlimit(RLIMIT_NOFILE, &rlim))
            nfiles = rlim.rlim_cur;
        for( fd = 0; fd < nfiles; ++fd )
            close(fd);
        open("/dev/null", 2);
        dup2(0, 1);
        dup2(0, 2);
        setpgid(0, 0);
        ptrace(PTRACE_TRACEME, 0, 0, 0);
        execvp(argv[0], argv);
        exit(0);
    }
    if (hangpid < 0)
        return 0;
    p = new Localproc;
    if (!p) {
        kill(9, hangpid);
        return 0;
    }
    p->sigmsk = sigmaskinit();
    p->pid = hangpid;
    if (!procwait(p, 0)) {
        delete p;
        return 0;
    }
    if (p->state.state == UNIX_BREAKED)
        p->state.state = UNIX_HALTED;
    p->opencnt = 0;
    p->next = phead;
    phead = p;
    return hangpid;
}
“procwait”中的“waitpid”只是挂起。如果我用 上面的代码,并运行一个'ps',我可以看到'pi'已经分叉 但是还没有调用exec,因为命令行仍然是 “pi”,而不是我正在分叉的二进制文件的名称。我发现 如果我删除“raise”,pi仍然挂起,但是现在是“ps” 显示分叉程序具有正在执行的二进制文件的名称 检查,这表明它已经执行了exec

因此,据我所知,我正在遵循文件化的程序 控制一个分叉的进程,但它不工作


Noel Hunt

我发现了这个问题(正如Nate所指出的,我自己的代码),但在我运行“strace pi”之前,原因还不清楚。很明显,有一个SIGCHLD处理程序,它正在执行等待。父级进入wait,SIGCHLD被传递,处理程序等待并获取子级的状态,然后在父级中重新启动wait并挂起,因为状态不再发生任何更改。SIGCHLD处理程序是有意义的,因为pi希望被告知子进程中的状态更改。我使用的“pi”的第一个版本是Solaris版本,它使用/proc进行过程控制,因此没有使用“wait”来获取子状态,因此我在Solaris版本中没有看到这个问题。

我发现了这个问题(正如Nate指出的,我自己的代码),但在运行“strace pi”之前,原因还不清楚。很明显,有一个SIGCHLD处理程序,它正在执行等待。父级进入wait,SIGCHLD被传递,处理程序等待并获取子级的状态,然后在父级中重新启动wait并挂起,因为状态不再发生任何更改。SIGCHLD处理程序是有意义的,因为pi希望被告知子进程中的状态更改。我使用的第一个“pi”版本是Solaris版本,它使用/proc进行过程控制,因此没有使用“wait”来获取子状态,因此我在Solaris版本中没有看到这个问题。

你能把它转换成一个,有人可以编译、运行和测试吗?我没有看到
raise()
在此版本的代码中。注意,
waitpid
只会在子进程停止时返回,而就代码而言,我看不到任何会使它停止的东西。你希望它什么时候停止?要回答这个问题,把它变成一个最小的可复制的例子,问题是,非常严格的例子,例如可以在网上找到的,工作。也就是说,父对象分叉,在子对象中它调用'ptrace(ptrace_TRACEME,0,0),然后exec的东西,比如'ls-l'。另一方面,父级执行等待。当等待返回时,父级现在处于控制中,可以设置寄存器等。我必须编写没有“raise()”的版本,但正如我所说,它不会改变结果,除了“raise”之外,子级的argv[]是“pi”本身的名称,这意味着子级没有执行;如果我删除'raise',等待仍然挂起,但是ps显示子对象中的argv现在具有子对象中的程序exec'd的名称。这表明SIGSTOP阻止了forked子级访问exec,但是我已经看到在这个上下文中的网络示例中使用了“raise”。然而,问题在于等待;为什么它没有返回?至于你关于没有看到任何会使它停止的东西的评论,我的理解是PTRACE_TRACEME实际上会导致孩子在第一次执行时停止。你能把它变成一个,有人可以编译、运行和测试吗?我在这个版本的代码中没有看到一个
raise()
。注意,
waitpid
只会在子进程停止时返回,而就代码而言,我看不到任何会使它停止的东西。你希望它什么时候停止?要回答这个问题,把它变成一个最小的可复制的例子,问题是,非常严格的例子,例如可以在网上找到的,工作。也就是说,父对象分叉,在子对象中它调用'ptrace(ptrace_TRACEME,0,0),然后exec的东西,比如'ls-l'。另一方面,父级执行等待。当等待返回时,父级现在处于控制中,可以设置寄存器等。我必须编写没有“raise()”的版本,但正如我所说,它不会改变结果,除了“raise”之外,子级的argv[]是“pi”本身的名称,这意味着子级没有执行;如果我删除'raise',等待仍然挂起,但是ps显示子对象中的argv现在具有子对象中的程序exec'd的名称。这表明SIGSTOP阻止了forked子级访问exec,但是我已经看到在这个上下文中的网络示例中使用了“raise”。然而,问题在于等待;为什么它没有返回?至于你关于没有看到任何东西会使它停止的评论,我的理解是,PTRACE_TRACEME实际上会导致孩子在第一次执行时停止。
int Hostfunc::procwait(Localproc *p, int flag){
    int tstat;
    int cursig;

again:
    if (p->pid != waitpid(p->pid, &tstat, (flag&WAIT_POLL)? WNOHANG: 0))
        return 0;
    if (flag & WAIT_DISCARD)
        return 1;
    if (WIFSTOPPED(tstat)) {
        cursig = WSTOPSIG(tstat);
        if (cursig == SIGSTOP)
            p->state.state = UNIX_HALTED;
        else if (cursig == SIGTRAP)
            p->state.state = UNIX_BREAKED;
        else {
            if (p->state.state == UNIX_ACTIVE &&
                !(p->sigmsk&bit(cursig))) {
                ptrace(PTRACE_CONT, p->pid, 1, cursig, 0);
                goto again;
            }
            else {
                p->state.state = UNIX_PENDING;
                p->state.code = cursig;
            }
        }
    } else {
        p->state.state = UNIX_ERRORED;
        p->state.code = WEXITSTATUS(tstat) & 0xFFFF;
    }
    return 1;
}