Defer assigning accepted socket until immediately before handler.
Fixes a problem in the reactor-based async_accept, if the
basic_socket::assign() operation throws due to an out-of-memory
condition.
diff --git a/asio/include/asio/detail/reactive_socket_accept_op.hpp b/asio/include/asio/detail/reactive_socket_accept_op.hpp
index 2a6fe75..11b81d5 100644
--- a/asio/include/asio/detail/reactive_socket_accept_op.hpp
+++ b/asio/include/asio/detail/reactive_socket_accept_op.hpp
@@ -41,7 +41,8 @@
state_(state),
peer_(peer),
protocol_(protocol),
- peer_endpoint_(peer_endpoint)
+ peer_endpoint_(peer_endpoint),
+ addrlen_(peer_endpoint ? peer_endpoint->capacity() : 0)
{
}
@@ -50,34 +51,38 @@
reactive_socket_accept_op_base* o(
static_cast<reactive_socket_accept_op_base*>(base));
- std::size_t addrlen = o->peer_endpoint_ ? o->peer_endpoint_->capacity() : 0;
socket_type new_socket = invalid_socket;
status result = socket_ops::non_blocking_accept(o->socket_,
o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0,
- o->peer_endpoint_ ? &addrlen : 0, o->ec_, new_socket) ? done : not_done;
+ o->peer_endpoint_ ? &o->addrlen_ : 0, o->ec_, new_socket)
+ ? done : not_done;
+ o->new_socket_.reset(new_socket);
ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_accept", o->ec_));
- // On success, assign new connection to peer socket object.
- if (new_socket != invalid_socket)
- {
- socket_holder new_socket_holder(new_socket);
- if (o->peer_endpoint_)
- o->peer_endpoint_->resize(addrlen);
- o->peer_.assign(o->protocol_, new_socket, o->ec_);
- if (!o->ec_)
- new_socket_holder.release();
- }
-
return result;
}
+ void do_assign()
+ {
+ if (new_socket_.get() != invalid_socket)
+ {
+ if (peer_endpoint_)
+ peer_endpoint_->resize(addrlen_);
+ peer_.assign(protocol_, new_socket_.get(), ec_);
+ if (!ec_)
+ new_socket_.release();
+ }
+ }
+
private:
socket_type socket_;
socket_ops::state_type state_;
+ socket_holder new_socket_;
Socket& peer_;
Protocol protocol_;
typename Protocol::endpoint* peer_endpoint_;
+ std::size_t addrlen_;
};
template <typename Socket, typename Protocol, typename Handler>
@@ -106,6 +111,10 @@
ptr p = { asio::detail::addressof(o->handler_), o, o };
handler_work<Handler> w(o->handler_);
+ // On success, assign new connection to peer socket object.
+ if (owner)
+ o->do_assign();
+
ASIO_HANDLER_COMPLETION((*o));
// Make a copy of the handler so that the memory can be deallocated before
@@ -165,6 +174,10 @@
ptr p = { asio::detail::addressof(o->handler_), o, o };
handler_work<Handler> w(o->handler_);
+ // On success, assign new connection to peer socket object.
+ if (owner)
+ o->do_assign();
+
ASIO_HANDLER_COMPLETION((*o));
// Make a copy of the handler so that the memory can be deallocated before
diff --git a/asio/src/examples/cpp11/http/server/server.cpp b/asio/src/examples/cpp11/http/server/server.cpp
index 123866c..fa76a4d 100644
--- a/asio/src/examples/cpp11/http/server/server.cpp
+++ b/asio/src/examples/cpp11/http/server/server.cpp
@@ -17,7 +17,7 @@
server::server(const std::string& address, const std::string& port,
const std::string& doc_root)
- : io_context_(),
+ : io_context_(1),
signals_(io_context_),
acceptor_(io_context_),
connection_manager_(),