Consider the following code that simulates a synchronous connect with timeout using async connect:
{
boost::asio::steady_timer timer{io_service, timeout};
timer.async_wait([&socket](boost::system::error_code const& code) {
if (!code)
socket.close();
});
auto future = boost::asio::async_connect(socket, endpoint, boost::asio::use_future);
future.get();
}
/* detect post-success cancelation? */
if (!socket.is_open()) {
}
If I understand asio documentation correctly, I cannot guarantee that the timer handler won't close the socket after is_open() has already returned true, because this sequence of events is possible:
- connect completes successfully
- timer expires, queuing the handler with code == success
- timer is destroyed, but the already queued handler can't be recalled
- is_open() returns true, so we think we're golden
- handler runs, canceling our socket because code == success
- future operations using the socket fail because we erroneously believed it's still open
How do I fix this code to make it safe against this scenario?