为什么进程在 execv 失败时会创建一个僵尸进程,而在 execv 成功并终止时则不会?

Why does a process create a zombie if execv fails, but not if execv is successful and terminates?

所以我对我的 C 程序的行为感到困惑。我正在使用结构,

int pid = fork();
if (pid == 0) {
    if(file_upload_script_path) {
        rc = execv(file_upload_script_path, args);
        if(rc == -1) {   
            printf("Error has occured when starting file_upload.exp!\n");
            exit(0);
        }
    } else {   
        printf("Error with memory allocation!\n");
    }
}
else {
    printf("pid=%d\n", pid);
}

分叉进程和运行 用于文件上传的脚本。脚本将通过完成上传或失败自行安全终止。

现在,脚本路径出现问题,导致 execv 失败。在这里,我注意到如果 execv 完成,子进程将成功终止,但如果它失败 (r==-1) 并且我退出该进程,它将变成僵尸。有人知道为什么会这样吗?

注意这里,我知道子进程为什么会变成僵尸了。我感到困惑的是,如果 execv 有效,为什么进程不会变成僵尸。

编辑:

我有一个关于 errno 和错误原因的问题。错误的原因是已知的。构建过程出现问题,因此脚本路径与预期不同。

但是,这可能会再次发生,我想确保我的程序不会在它开始生成僵尸时开始生成僵尸。在某些情况下创建僵尸而不在其他情况下创建僵尸的行为非常令人困惑。

BR 帕特里克

在这种情况下,当execv失败时,子进程被杀死。我认为有趣的部分是调用 exec 系列函数时发生的情况。

exec 系列函数用您将要执行的二进制文件的新映像替换进程的当前映像。

因此,无论 的代码都不会 保留 - 脚本中的错误会导致其死亡。

在这里,父进程需要使用函数的等待风格(读取:waitpid)来监听子进程的死亡。

当你说脚本有问题时,这意味着execv实际上成功地创建了新图像;但后者自己失败了。

这就是我认为正在发生的事情...

如果 if (rc==-1) 的 printf 正在执行,那么也许将 exit(0) 更改为 _exit(0) 应该会处理它。

如果你不想创建僵尸进程,你的程序必须收割僵尸进程,无论他们是否调用 execv 或不调用它,也不管 execv 调用是否成功。要获取僵尸进程 "automagically" 处理 SIGCHLD 信号:

void handle_sigchld(int sig) {
    int saved_errno = errno;
    while (waitpid((pid_t)(-1), 0, WNOHANG) > 0) {}
    errno = saved_errno;
}

int main() {
    signal(SIGCHLD, handle_sigchld);
    // rest of your program....
}

灵感来自(没有……抄袭):this link

或者您可能只想获取这个指定的 child,因为稍后您想要调用 fork() 并处理 child 的 return 值。然后将 parent 中的 fork() 中的 returned pid 传递给信号处理程序,并在需要时将 wait 传递给 sigchld 中的此 pid(进行一些检查,例如. 如果 pid 已经完成则忽略未来的 SIGCHLD 等...)