In my asio based application I have problems with the error handling. I use asio single-threaded/single io_service with the async_read / async_write functions, and when the error-code passed to me in the completion handler is not null, any call to its .message() method results in a segfault, because the error-category pointer points to null. However, the actual value is always correct.
Weirdly I am not able to reproduce this in a test application. This is essentially what I'm doing, but in case of an error, calling message() here works as expected:
void do_write(std::shared_ptr<std::vector<unsigned char>> , std::shared_ptr<boost::asio::ip::tcp::socket> );
void do_read(std::shared_ptr<std::vector<unsigned char>> buf, std::shared_ptr<boost::asio::ip::tcp::socket> sock)
{
boost::asio::async_read(*sock, boost::asio::buffer(*buf), boost::asio::transfer_exactly(100000),
[sock, buf](const boost::system::error_code& ec, std::size_t bytes)
{
std::cout << "read\n";
if (ec) {
std::cout << ec.message() << std::flush;
} else {
do_write(buf, sock);
}
});
}
void do_write(std::shared_ptr<std::vector<unsigned char>> buf, std::shared_ptr<boost::asio::ip::tcp::socket> sock)
{
boost::asio::async_write(*sock, boost::asio::buffer(*buf), [sock, buf](const boost::system::error_code& ec, std::size_t bytes)
{
std::cout << "write\n";
if (ec) {
std::cout << ec.message() << std::flush;
} else {
do_read(buf, sock);
}
});
}
int main()
{
auto buf = std::make_shared<std::vector<unsigned char>>(100000);
unsigned short port = 1113;
boost::asio::io_service ios;
boost::asio::ip::tcp::acceptor acptr {ios, boost::asio::ip::tcp::endpoint{boost::asio::ip::tcp::v4(), port}};
auto socket = std::make_shared<boost::asio::ip::tcp::socket>(acptr.get_io_service());
acptr.async_accept(*socket, [socket, buf](const boost::system::error_code& ec)
{
do_read(buf, socket);
});
ios.run();
}
I do not think it is a problem with lifetimes of my application, AddressSanitizer does not find any potential errors and I can shift hundreds of megabytes of data without any problems. Also if I just uncomment the call to message(), the server continues to run fine and correctly handles new connections. Anyway, here is the callstack when the crash occurs:
https://gist.github.com/mariusherzog/82f24caf9eea4d94946706aa8c025ef1 The category points to null from frame 11 upwards.
I use linux with boost 1.62 with clang 3.9.1 and gcc 5.4.0