Boost Process on_exit回调重启进程后程序崩溃问题排查求助
进程重启后崩溃及Valgrind报错的修复方案
问题描述
尝试在旧进程退出后立即重启相同进程,执行几次后程序崩溃。Valgrind报告与handler相关的无效读写操作,移除lambda内启动新进程的调用后,Valgrind错误消失。示例代码仅针对单个进程,目标是让多个此类可自重启的进程同时运行:
std::function<void(int, const std::error_code&)> on_exit; on_exit = [this, &on_exit](int exit, const std::error_code& ec_in) { // error handling client.wait(); client = bp::child(path_to_client, io_context, bp::on_exit=on_exit); }; client = bp::child(path_to_client, io_context, bp::on_exit=on_exit); io_context.run();
注:client、path_to_client和io_context均为类成员变量。
问题根源
lambda中捕获了on_exit的引用,而std::function是可移动/可赋值的对象。每次在lambda内重启进程时,bp::child会持有这个handler的引用,后续重新赋值on_exit或销毁原std::function对象时,会导致handler调用时访问无效内存地址,触发Valgrind的无效读写报错。
修复方案
1. 用智能指针保证handler生命周期安全
避免捕获on_exit的引用,改用std::shared_ptr包裹std::function,让lambda捕获智能指针副本,确保handler在所有引用者使用期间不会被销毁:
auto on_exit = std::make_shared<std::function<void(int, const std::error_code&)>>(); *on_exit = [this, on_exit](int exit_code, const std::error_code& ec) { // error handling client.wait(); client = bp::child(path_to_client, io_context, bp::on_exit=*on_exit); }; client = bp::child(path_to_client, io_context, bp::on_exit=*on_exit); io_context.run();
2. 优化client对象的替换方式
直接赋值client = bp::child(...)会销毁原有bp::child对象,可能导致旧对象持有的handler引用失效。改用swap操作避免生命周期冲突:
*on_exit = [this, on_exit](int exit_code, const std::error_code& ec) { // error handling client.wait(); bp::child new_client(path_to_client, io_context, bp::on_exit=*on_exit); client.swap(new_client); };
3. 多进程场景的额外注意事项
- 每个自重启进程需独立持有自己的handler智能指针,避免多进程共享同一handler引发竞态或生命周期问题。
- 若使用多线程运行
io_context,需用io_context::strand序列化handler执行,防止并发修改client等类成员变量。
内容的提问来源于stack exchange,提问作者luxean
相关产品推荐
相关产品推荐

