Linux环境下waitpid()为何无法等待回收所有子进程?
问题原因
- SIGCHLD信号不可靠导致漏回收
Linux下常规信号不支持排队,若短时间内多个子进程同时终止,内核只会向父进程发送一次SIGCHLD信号。你当前的信号处理函数中仅调用一次wait(),每次信号触发最多只能回收1个子进程,其余已终止的子进程无法被处理,自然不会打印终止日志。 - 等待逻辑存在缺陷
- 并发控制完全不符合预期:你设置的
i%100==99才执行等待,意味着每轮会连续创建100个子进程,和你要求的最多同时运行10个的目标完全不符,短时间大量子进程退出进一步放大了信号合并漏处理的问题。 - 收尾等待不完整:父进程最后仅等待了最后一个创建的子进程,其余未被回收的子进程会随着父进程退出被系统接管,不会在父进程中输出终止日志。
- 批量等待逻辑错误:你每100个子进程仅等待该批次第一个子进程
old,其余99个子进程完全没有主动等待逻辑,完全依赖信号处理回收,进一步提升了漏回收的概率。
- 并发控制完全不符合预期:你设置的
修复方案
- 修改SIGCHLD信号处理函数,循环回收所有已终止的子进程:
void sig_chld(int signo) { pid_t pid; int stat; // WNOHANG表示没有已终止子进程时立刻返回,循环把当前所有已终止的子进程全部回收 while( (pid = waitpid(-1, &stat, WNOHANG)) > 0 ){ fprintf(stderr, "child [%d] terminate\n",pid); } return; }
- 修正并发控制逻辑:如果要限制最多同时运行10个子进程,可改为每创建10个子进程就阻塞等待所有子进程退出,或者维护运行中子进程计数,达到上限后等待任意子进程退出再继续创建。
- 父进程退出前增加全局等待逻辑,确保所有子进程都被回收:
// 父进程打印parent end前添加,阻塞等待所有剩余子进程退出 while( waitpid(-1, NULL, 0) > 0 );
内容的提问来源于stack exchange,提问作者user630900
相关产品推荐
相关产品推荐

