waitpid() 失败:没有这样的文件或目录

时间:2021-02-09 20:52:19

标签: c unix

我试图在子进程中调用 exec(),并在父进程中等待。当我在父进程中使用 'wait()' 时它工作正常。但是我喜欢获取子进程的状态码,所以我使用了waitpid(),但它等待失败。不知道为什么,请帮忙,不胜感激!

int runcgi(int socket, char *uri, char *dir)
{   
    pid_t pid; 
    int status = 0;
    char command[MAXPATHLEN];
    
    snprintf(command, MAXPATHLEN, "%s%s", dir, strsep(&uri, "?"));
    printf("%s\n", command);
    
    if ((pid = fork()) < 0)
    {   
        syslog(LOG_INFO, "Error forking");
        return -1;
    }
    else if (pid == 0)
    {   
        if (dup2(socket, STDOUT_FILENO) < 0)
        {    
            syslog(LOG_ERR, "Error duping STDOUT_FILENO");
            status = -1;
            exit(EXIT_FAILURE);
        }
        
        if (dup2(socket, STDERR_FILENO) < 0)
        {    
            syslog(LOG_ERR, "Error duping STDERR_FILENO");
            status = -1;
            exit(EXIT_FAILURE);
        }
        
        if (setenv("PATH", dir, 1) != 0)
        {    
            syslog(LOG_ERR, "Failed to set PATH=%s", dir);
            status = -1;
            err(EXIT_FAILURE, "Failed to set PATH=%s", dir);
        }
        
        if (uri != NULL && strlen(uri) > 0)
        {   
            char *var;
            while ((var = strsep(&uri, "&")) != NULL)
            {   
                if (putenv(var) == -1)
                {    
                    syslog(LOG_ERR, "Failed to set env %s", var);
                    status = -1;
                    err(EXIT_FAILURE, "Failed to set env %s", var);
                }
            }
        }
        
        execlp(command, basename(command), (char *)0);
        status = -1;
    }
    
    if (waitpid(pid, &status, 0) == -1)
    {   
        syslog(LOG_ERR, "waitpid failed");
        err(EXIT_FAILURE, "waitpid failed");
    }
    
    if (WIFEXITED(status))
    {   
        return WEXITSTATUS(status);
    }

//  (void)wait(NULL);
    return status;
}

奇怪的是,当我检查 errno 时,我得到“没有这样的文件或目录”。

1 个答案:

答案 0 :(得分:1)

status 传递给其父级的代码在哪里?孩子将 status 设置为 -1 但随后没有对它做任何事情!你想让孩子_exit(status);吗?

你收到一个错误,因为孩子试图等待一个他没有的孩子 有。此处的错误“没有此类文件或目录”仅表示 PID 不对应于子进程中的任何进程,因为子进程从 fork 获得零返回。

这是孩子身上发生的事情:

    else if (pid == 0)
    {
        ... // lots of code here
        execlp(command, basename(command), (char *)0);
        status = -1;
    }
    
    if (waitpid(pid, &status, 0) == -1)

请注意,如果 execlp 失败,请将 status 设置为 -1。但是你什么都不用做。然后您在子进程中调用 waitpid ,但是 pid 在这里为零!您错过了孩子对 _exit 的呼叫。