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

添加waitpid后Linux父子进程均挂起的问题排查

问题分析:添加waitpid导致父子进程挂起的原因

核心问题拆解

  1. scanf("%s")的读取特性
    scanf("%s", cmd)会持续读取字符,直到遇到**空白字符(空格、换行、制表符等)**才会返回并结束本次读取。如果没有读到空白字符,哪怕管道里已经有"close"内容,它也会一直阻塞等待更多输入。

  2. 管道写端的关闭时机差异

    • 未加waitpid时:父进程写完"close"后直接return 0退出,操作系统会自动关闭父进程持有的所有文件描述符(包括管道的写端)。此时子进程的scanf读取到管道的EOF(写端完全关闭),scanf返回EOF,循环终止,子进程正常退出。
    • 添加waitpid后:父进程写完"close"后调用waitpid等待子进程退出,但此时父进程仍持有管道写端(管道写端未完全关闭,只有父进程关闭后才算彻底关闭)。子进程的scanf既没读到空白字符,也没收到EOF,会一直阻塞在读取操作上;父进程则阻塞在waitpid等待子进程退出,形成双向阻塞死锁。

验证与解决方案

方案1:手动关闭管道写端

在父进程写入后立即关闭管道写端,让子进程收到EOF:

B = write(child.fd, "close", 5); if (B != 5) return -1;
close(child.fd); // 手动关闭管道写端
waitpid(child.pid, NULL, 0);

此时子进程的scanf会收到EOF,循环终止,子进程正常退出,父进程的waitpid也能顺利返回。

方案2:写入时添加空白终止符

在写入的字符串末尾加上换行符(空白字符的一种),让scanf直接结束读取:

B = write(child.fd, "close\n", 6); // 写入换行符作为终止符
waitpid(child.pid, NULL, 0);

子进程的scanf读到换行符后立即返回,无需等待EOF,父子进程都能正常执行。

总结

问题本质是scanf("%s")的读取逻辑依赖空白符或EOF来结束,添加waitpid后父进程未及时关闭管道写端,也未提供空白终止符,导致双方陷入阻塞死锁。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 18:54:54