使用boost::process::child执行长输出命令导致程序挂起如何解决
问题根因
该卡死现象是管道缓冲区的阻塞机制触发了死锁:
- 类Unix系统默认管道缓冲区大小仅为4~64KB,Windows平台也存在类似的上限
- 你的代码将子进程的标准输出、标准错误都重定向到管道,但在调用
cp.wait()前完全没有读取管道内的数据 - 当执行
ps aux这类输出量较大的命令时,输出内容很快就会填满管道缓冲区,此时系统会挂起子进程,等待管道读端读取数据腾出空间后子进程才能继续运行 - 此时父进程阻塞在
cp.wait()等待子进程退出,子进程阻塞在写管道等待父进程读数据,形成死锁,程序就会永久无响应
修复方案
方案1:先读取管道数据再等待子进程退出
启动子进程后先读完所有管道输出,再调用wait()即可,示例代码如下:
#include <boost/process.hpp> #include <iostream> #include <string> namespace bp = boost::process; // 逻辑部分示例 try{ bp::ipstream out_stream; child cp(cmd, param, (bp::std_out & bp::std_err) > out_stream); // 先读取全部输出 std::string line; while (std::getline(out_stream, line)) { // 此处可自行处理输出内容,比如存储或打印 std::cout << line << '\n'; } cp.wait(); return_code = cp.exit_code(); }catch (const bp::process_error& e){ return_code = -1; }
注意:不要手动拼接
cmd + " " + param作为执行命令,当参数包含空格、特殊字符时会出现解析错误,直接向child构造函数依次传递命令、参数的写法更安全。
方案2:异步读取管道
如果不希望主线程阻塞在读操作上,可以使用boost.process提供的异步IO接口,并行执行读管道和等待子进程的逻辑。
方案3:无需获取输出的场景
如果你不需要拿到子进程的输出内容,可以直接将输出重定向到空设备,不会触发缓冲区阻塞:
child cp(cmd, param, (bp::std_out & bp::std_err) > bp::null); cp.wait();
内容的提问来源于stack exchange,提问作者YZY
相关产品推荐
相关产品推荐

