问题
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();
}
Now this works perfectly fine. But if I use boost::Spawn() to do asyncRead() it crashes.
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();
}
The stack trace for the crash is:
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<>()
I want to make it work with boost::spawn()
. What will happen to spawn()
once my work()
returns?
回答1:
For starters, your code cannot possibly compile (handler
must be a non-static member function of Worker
, but that means it doesn't satisfy the handler requirements for async_receive_from
.
But the problem you ask about appears simpler:
auto ob1 = std::make_shared<Worker>(io_service);
Creates a shared pointer
boost::asio::spawn(*io_service, [ob1](
boost::asio::yield_context yield) {
Posts a coro onto the service, that holds a copy of ob1
so it stays alive. So far so good.
ob1->AsyncRead();
This does an async_recieve_from
, which naturally returns immediately, the coro is done and ob1
is released. But async_receive_from
is still pending on the service.
If you want to use async operations inside a coro, you have to pass the yield_context as a completion token. You didn't do that.
Your code should conceptually look like:
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
});
来源:https://stackoverflow.com/questions/52783731/program-crash-with-boostasiospawn-and-socketasync-receive-from