You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环调用fork()创建子进程后程序挂起的问题求助

问题分析与修复

核心问题

你的代码中子进程分支(case 0)缺少退出逻辑:

  • 当execlp执行成功时,子进程的代码会被sighandler完全替换,不会执行后续代码,这部分是正常的。
  • 但如果execlp执行失败(比如./sighandler不存在、权限不足、参数错误等),子进程会继续执行default分支的代码——也就是调用wait(&stat)。此时子进程没有创建任何子进程,wait会永久阻塞;同时父进程也在wait这个子进程,最终导致双向阻塞,程序挂起。

另外,原代码逻辑是创建一个子进程就立刻等待它退出,会变成串行执行5个子进程,虽然能完成功能,但如果想并行创建子进程再统一等待,可调整逻辑,但当前挂起问题的核心还是子进程分支的退出处理。

修复后的代码

#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int stat;
    pid_t pd;
    for (int i = 0; i < 5; i++) {
        switch (pd = fork())
        {
            case -1:
                perror("fork error!");
                exit(1);
            case 0:
                // 执行execlp,失败则直接退出子进程
                execlp("./sighandler", "./sighandler", argv[1], argv[2], (char *)NULL);
                // 走到这里说明execlp失败,打印错误并退出
                perror("execlp failed");
                exit(EXIT_FAILURE);
            default:
                // 等待当前子进程退出
                if (wait(&stat) == -1) {
                    perror("wait error!");
                    exit(2);
                }
                printf("PID = %d | Exit Status = %d\n", pd, WEXITSTATUS(stat));
        }
    }
    return 0;
}

关键修改点

  1. 在case 0分支的execlp之后添加错误处理:
    • execlp只有执行失败时才会返回,所以一旦走到这行代码之后,直接打印错误并调用exit终止子进程,避免子进程进入default分支执行wait。
  2. 优化打印信息的可读性,明确标注退出状态的含义。

可选优化:并行创建子进程后统一等待

如果希望5个子进程并行执行,而非串行等待,可先批量创建所有子进程,再循环等待全部退出,示例代码如下:

#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int stat;
    pid_t pd;
    // 批量创建子进程
    for (int i = 0; i < 5; i++) {
        switch (pd = fork())
        {
            case -1:
                perror("fork error!");
                exit(1);
            case 0:
                execlp("./sighandler", "./sighandler", argv[1], argv[2], (char *)NULL);
                perror("execlp failed");
                exit(EXIT_FAILURE);
            default:
                printf("Created child PID: %d\n", pd);
                break;
        }
    }
    // 统一等待所有子进程退出
    while ((pd = wait(&stat)) != -1) {
        printf("PID = %d | Exit Status = %d\n", pd, WEXITSTATUS(stat));
    }
    return 0;
}

内容的提问来源于stack exchange,提问作者fdnull

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 14:41:13