boost::asio::spawn 和 socket::async_receive_from 程序崩溃
program crash with boost::asio::spawn and socket::async_receive_from
int main() {
boost::asio::io_service io_service;
Worker ob1(&io_service);
ob1.AsyncRead();
io_service.run();
}
void Worker::AsyncRead() {
socket.async_receive_from(buffer,endpoint, handler);
}
void handler (const boost::system::error_code& error, size_t bytes_received) {
if(!error)
handleData();
AsyncRead();
}
现在一切正常。但是如果我使用 boost::Spawn() 来执行 asyncRead() 它会崩溃。
void work(boost::asio::io_service* io_service) {
auto ob1 = std::make_shared<Worker>(io_service);
boost::asio::spawn(*io_service, [ob1](
boost::asio::yield_context yield) {
ob1->AsyncRead();
});
}
int main() {
boost::asio::io_service io_service;
work(&io_service);
io_service.run();
}
崩溃的堆栈跟踪是:
PC: @ 0x4e3502 boost::asio::basic_io_object<>::get_service()
*** SIGSEGV (@0x18) received by PID 25135 (TID 0x7f6bde13b7c0) from PID 24; stack trace: ***
@ 0x7f6bdd37d390 (unknown)
@ 0x4e3502 boost::asio::basic_io_object<>::get_service()
@ 0x4e3074 boost::asio::basic_datagram_socket<>::async_receive_from<>()
我想让它与 boost::spawn()
一起使用。一旦我的 work()
returns,spawn()
会怎样?
首先,您的代码可能无法编译(handler
必须是 Worker
的非静态成员函数,但这意味着它不满足 [=16= 的处理程序要求].
不过你问的问题比较简单:
auto ob1 = std::make_shared<Worker>(io_service);
创建共享指针
boost::asio::spawn(*io_service, [ob1](
boost::asio::yield_context yield) {
将一个 coro 发布到服务上,其中包含 ob1
的副本,因此它保持活动状态。到目前为止一切顺利。
ob1->AsyncRead();
这会执行一个 async_recieve_from
,这自然会立即 returns,coro 完成并且 ob1
被释放。但是 async_receive_from
仍在等待服务。
如果你想在 coro 中使用异步操作,你必须将 yield_context 作为完成标记传递。你没有那样做。
您的代码在概念上应如下所示:
void work(boost::asio::io_service* io) {
boost::asio::spawn(*io_service, [io](boost::asio::yield_context yield) {
udp::socket socket(*io);
// ... more
udp::endpoint ep;
char buffer[1024];
socket.async_receive_from(buffer, ep, yield); // throws on error
});
int main() {
boost::asio::io_service io_service;
Worker ob1(&io_service);
ob1.AsyncRead();
io_service.run();
}
void Worker::AsyncRead() {
socket.async_receive_from(buffer,endpoint, handler);
}
void handler (const boost::system::error_code& error, size_t bytes_received) {
if(!error)
handleData();
AsyncRead();
}
现在一切正常。但是如果我使用 boost::Spawn() 来执行 asyncRead() 它会崩溃。
void work(boost::asio::io_service* io_service) {
auto ob1 = std::make_shared<Worker>(io_service);
boost::asio::spawn(*io_service, [ob1](
boost::asio::yield_context yield) {
ob1->AsyncRead();
});
}
int main() {
boost::asio::io_service io_service;
work(&io_service);
io_service.run();
}
崩溃的堆栈跟踪是:
PC: @ 0x4e3502 boost::asio::basic_io_object<>::get_service()
*** SIGSEGV (@0x18) received by PID 25135 (TID 0x7f6bde13b7c0) from PID 24; stack trace: ***
@ 0x7f6bdd37d390 (unknown)
@ 0x4e3502 boost::asio::basic_io_object<>::get_service()
@ 0x4e3074 boost::asio::basic_datagram_socket<>::async_receive_from<>()
我想让它与 boost::spawn()
一起使用。一旦我的 work()
returns,spawn()
会怎样?
首先,您的代码可能无法编译(handler
必须是 Worker
的非静态成员函数,但这意味着它不满足 [=16= 的处理程序要求].
不过你问的问题比较简单:
auto ob1 = std::make_shared<Worker>(io_service);
创建共享指针
boost::asio::spawn(*io_service, [ob1](
boost::asio::yield_context yield) {
将一个 coro 发布到服务上,其中包含 ob1
的副本,因此它保持活动状态。到目前为止一切顺利。
ob1->AsyncRead();
这会执行一个 async_recieve_from
,这自然会立即 returns,coro 完成并且 ob1
被释放。但是 async_receive_from
仍在等待服务。
如果你想在 coro 中使用异步操作,你必须将 yield_context 作为完成标记传递。你没有那样做。
您的代码在概念上应如下所示:
void work(boost::asio::io_service* io) {
boost::asio::spawn(*io_service, [io](boost::asio::yield_context yield) {
udp::socket socket(*io);
// ... more
udp::endpoint ep;
char buffer[1024];
socket.async_receive_from(buffer, ep, yield); // throws on error
});