英文:
Chaining Boost Process on_exit completion handlers
问题
I'm trying to restart the same process right after the old one exits, but after few executions my program crashes. Valgrind is reporting invalid reads and writes related to the handler, but I'm having no luck with getting closer to a fix. The sample code shows only one process, but my goal is to have a few of these processes that restart themselves running at the same time.
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();
The client
, path_to_client
, and io_context
are all members of a class.
Removing the call to launch the new process inside the lambda fixes the valgrind errors.
英文:
I'm trying to restart the same process right after the old one exits, but after few executions my program crashes. Valgrind is reporting invalid reads and writes related to the handler, but I'm having no luck with getting closer to a fix. The sample code shows only one process, but my goal is to have a few of these processes that restart themselves running at the same time.
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();
The client
, path_to_client
, and io_context
are all members of a class.
Removing the call to launch the new process inside the lambda fixes the valgrind errors.
答案1
得分: 0
on_exit
是一个本地函数,但你通过引用捕获它。通过使用成员变量如 client
等方式使其存活足够长来修复它。
以下是一个自包含的演示程序:
#include <boost/process.hpp>
#include <iostream>
namespace bp = boost::process;
struct ProgramX {
boost::asio::io_context io_context;
bp::child client;
unsigned remaining = 0;
std::function<void(int, std::error_code)> on_exit = [this](int exit, std::error_code ec) {
client.wait();
std::cout << "exit code " << exit << " (" << ec.message() << ")" << std::endl;
// 错误处理...
if (--remaining)
launch();
};
void launch() {
boost::filesystem::path path_to_client = "/bin/sleep";
std::vector<std::string> args = {"1"};
client = bp::child(path_to_client, args, io_context, bp::on_exit = on_exit);
}
void foo(unsigned how_many_runs) {
remaining = how_many_runs;
launch();
io_context.run();
}
};
int main() {
ProgramX x;
x.foo(5);
}
更新:早期 Boost 版本中的错误
在尝试在线操作时,我注意到... 它的表现不如预期。
- Boost 1.82.0.beta1 对我来说运行良好
- Boost 1.81.0 不行
- Boost 1.79.0 也不行(Wandbox,Coliru,Compiler Explorer 没有
/bin/sleep
)
在我的本地机器上,如下所示:
所以很有可能你也需要尽早升级到 Boost 1.82.0。
【注】:请注意,两者都标记为 108200,但你可以看到我只切换了进程子模块的发布标签。
1: https://i.stack.imgur.com/rMCoP.gif
英文:
on_exit
is a local function, but you capture it by reference. Fix it by making it live long enough, e.g. by using a member variable like client
instead.
Here's a self-contained demo program:
#include <boost/process.hpp>
#include <iostream>
namespace bp = boost::process;
struct ProgramX {
boost::asio::io_context io_context;
bp::child client;
unsigned remaining = 0;
std::function<void(int, std::error_code)> on_exit = [this](int exit, std::error_code ec) {
client.wait();
std::cout << "exit code " << exit << " (" << ec.message() << ")" << std::endl;
// error handling...
if (--remaining)
launch();
};
void launch() {
boost::filesystem::path path_to_client = "/bin/sleep";
std::vector<std::string> args = {"1"};
client = bp::child(path_to_client, args, io_context, bp::on_exit = on_exit);
}
void foo(unsigned how_many_runs) {
remaining = how_many_runs;
launch();
io_context.run();
}
};
int main() {
ProgramX x;
x.foo(5);
}
UPDATE: Bugs in Earlier Boost Versions
When trying things online, I noticed that... it didn't work as expected.
- Boost 1.82.0.beta1 works fine for me
- Boost 1.81.0 doesn't (Wandbox)
- Boost 1.79.0 doesn't (Wandbox, Coliru, Compiler Explorer doesn't have
/bin/sleep
)
Here's a side-by-side on my local machine¹:
So in all likelihood, you (also) need to update to Boost 1.82.0 sooner rather than later.
¹ note both say 108200 but you can see me switching the release tag for just the process submodule
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论