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

C语言fork多进程场景下获取已终止子进程exit status问题排查

问题根因

  • 代码中的pid变量在for循环fork结束后,只会保留最后一次fork生成的子进程PID,后续while循环里反复调用waitpid(pid, ...)只会等待这一个子进程,其余子进程都会变成僵尸进程无法被回收,也拿不到它们的退出状态
  • 原逻辑没有对waitpid返回的状态值做解析,直接根据调用是否失败来累加成功/失败计数,统计逻辑完全错误
  • waitpid第一个参数传-1的时候才会等待任意一个子进程退出,这才是符合需求的逻辑

修复后完整代码

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

int main(int argc, char *argv[]) {
    pid_t pid;
    int i, stat, suc = 0, fail = 0;

    if (argc < 2){
        printf("Usage: ./wordcount.exe [File_1] [File_2] [...] [File_n]\n");
        exit(1);
    }

    for (i = 1; i < argc; i++){
        if ((pid = fork()) == 0){
            if (access(argv[i], F_OK) != 0){
                fprintf(stderr, "Child process %ld for %s does not exist\n", (long)getpid(), argv[i]);
                return 1;           
            }
            fprintf(stderr, "Child process %ld for %s: Number of words is: %d\n", (long)getpid(), argv[i], 0);
            exit(0);
        }
    }

    // 修复子进程等待与状态统计逻辑
    while(1){
        // 第一个参数传-1:等待任意子进程退出
        pid = waitpid(-1, &stat, 0);
        if (pid == -1) {
            // 没有更多子进程需要等待时退出循环
            if (errno == ECHILD) break;
            // 被信号中断则重试
            else if (errno == EINTR) continue;
            else perror("waitpid error");
        }
        // 解析子进程退出状态
        if (WIFEXITED(stat)) {
            int exit_code = WEXITSTATUS(stat);
            printf("pid = %d\t exit status=%d\n", pid, exit_code);
            if (exit_code == 0) suc++;
            else if (exit_code == 1) fail++;
        }
    }

    printf("Parent process created %d processes to count %d words in %d files\n", (suc + fail), 0, (suc + fail));
    printf("%d file(s) have been counted successfully!\n", suc);
    printf("%d file(s) did not exist.\n", fail);

    return 0;
}

核心修改点说明

  • 将waitpid第一个参数改为-1,表示等待任意一个子进程终止,每次调用返回终止的子进程PID
  • 新增状态解析逻辑:用WIFEXITED判断子进程是否正常退出,再用WEXITSTATUS获取子进程的返回值,根据返回值累加成功/失败计数
  • 退出循环的条件改为errno == ECHILD,表示当前没有剩余子进程需要等待,此时才终止循环

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 21:09:01