Fix async object lifetimes
This commit is contained in:
parent
124c7848c0
commit
855f39b321
|
@ -41,15 +41,15 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <nghttp2/asio_http2_server.h>
|
||||
|
||||
#include "asio_server_http2_handler.h"
|
||||
#include "asio_server_serve_mux.h"
|
||||
#include "util.h"
|
||||
#include "template.h"
|
||||
#include "util.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
|
@ -69,13 +69,10 @@ public:
|
|||
const boost::posix_time::time_duration &tls_handshake_timeout,
|
||||
const boost::posix_time::time_duration &read_timeout,
|
||||
SocketArgs &&... args)
|
||||
: socket_(std::forward<SocketArgs>(args)...),
|
||||
mux_(mux),
|
||||
: socket_(std::forward<SocketArgs>(args)...), mux_(mux),
|
||||
deadline_(socket_.get_io_service()),
|
||||
tls_handshake_timeout_(tls_handshake_timeout),
|
||||
read_timeout_(read_timeout),
|
||||
writing_(false),
|
||||
stopped_(false) {}
|
||||
read_timeout_(read_timeout), writing_(false), stopped_(false) {}
|
||||
|
||||
/// Start the first asynchronous operation for the connection.
|
||||
void start() {
|
||||
|
@ -83,7 +80,13 @@ public:
|
|||
|
||||
handler_ = std::make_shared<http2_handler>(
|
||||
socket_.get_io_service(), socket_.lowest_layer().remote_endpoint(ec),
|
||||
[this]() { do_write(); }, mux_);
|
||||
[ this, self = this->shared_from_this() ]() {
|
||||
if (!std::weak_ptr<connection>{self}.lock()) {
|
||||
return;
|
||||
}
|
||||
do_write();
|
||||
},
|
||||
mux_);
|
||||
if (handler_->start() != 0) {
|
||||
stop();
|
||||
return;
|
||||
|
@ -95,14 +98,22 @@ public:
|
|||
|
||||
void start_tls_handshake_deadline() {
|
||||
deadline_.expires_from_now(tls_handshake_timeout_);
|
||||
deadline_.async_wait(
|
||||
std::bind(&connection::handle_deadline, this->shared_from_this()));
|
||||
deadline_.async_wait([self = this->shared_from_this()](
|
||||
const boost::system::error_code &) {
|
||||
if (!std::weak_ptr<connection>{self}.lock())
|
||||
return;
|
||||
return self->handle_deadline();
|
||||
});
|
||||
}
|
||||
|
||||
void start_read_deadline() {
|
||||
deadline_.expires_from_now(read_timeout_);
|
||||
deadline_.async_wait(
|
||||
std::bind(&connection::handle_deadline, this->shared_from_this()));
|
||||
deadline_.async_wait([self = this->shared_from_this()](
|
||||
const boost::system::error_code &) {
|
||||
if (!std::weak_ptr<connection>{self}.lock())
|
||||
return;
|
||||
return self->handle_deadline();
|
||||
});
|
||||
}
|
||||
|
||||
void handle_deadline() {
|
||||
|
@ -117,49 +128,51 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
deadline_.async_wait(
|
||||
std::bind(&connection::handle_deadline, this->shared_from_this()));
|
||||
deadline_.async_wait([self = this->shared_from_this()](
|
||||
const boost::system::error_code &) {
|
||||
if (!std::weak_ptr<connection>{self}.lock())
|
||||
return;
|
||||
return self->handle_deadline();
|
||||
});
|
||||
}
|
||||
|
||||
void do_read() {
|
||||
auto self = this->shared_from_this();
|
||||
|
||||
deadline_.expires_from_now(read_timeout_);
|
||||
|
||||
socket_.async_read_some(
|
||||
boost::asio::buffer(buffer_),
|
||||
[this, self](const boost::system::error_code &e,
|
||||
std::size_t bytes_transferred) {
|
||||
if (e) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
socket_.async_read_some(boost::asio::buffer(buffer_), [
|
||||
this, self = this->shared_from_this()
|
||||
](const boost::system::error_code &e, std::size_t bytes_transferred) {
|
||||
if (!std::weak_ptr<connection>{self}.lock()) {
|
||||
return;
|
||||
}
|
||||
if (e) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (handler_->on_read(buffer_, bytes_transferred) != 0) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
if (handler_->on_read(buffer_, bytes_transferred) != 0) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
do_write();
|
||||
do_write();
|
||||
|
||||
if (!writing_ && handler_->should_stop()) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
if (!writing_ && handler_->should_stop()) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
do_read();
|
||||
do_read();
|
||||
|
||||
// If an error occurs then no new asynchronous operations are
|
||||
// started. This means that all shared_ptr references to the
|
||||
// connection object will disappear and the object will be
|
||||
// destroyed automatically after this handler returns. The
|
||||
// connection class's destructor closes the socket.
|
||||
});
|
||||
// If an error occurs then no new asynchronous operations are
|
||||
// started. This means that all shared_ptr references to the
|
||||
// connection object will disappear and the object will be
|
||||
// destroyed automatically after this handler returns. The
|
||||
// connection class's destructor closes the socket.
|
||||
});
|
||||
}
|
||||
|
||||
void do_write() {
|
||||
auto self = this->shared_from_this();
|
||||
|
||||
if (writing_) {
|
||||
return;
|
||||
}
|
||||
|
@ -187,18 +200,21 @@ public:
|
|||
// something, it does not expect timeout while doing it.
|
||||
deadline_.expires_from_now(read_timeout_);
|
||||
|
||||
boost::asio::async_write(
|
||||
socket_, boost::asio::buffer(outbuf_, nwrite),
|
||||
[this, self](const boost::system::error_code &e, std::size_t) {
|
||||
if (e) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
boost::asio::async_write(socket_, boost::asio::buffer(outbuf_, nwrite), [
|
||||
this, self = this->shared_from_this()
|
||||
](const boost::system::error_code &e, std::size_t) {
|
||||
if (!std::weak_ptr<connection>{self}.lock()) {
|
||||
return;
|
||||
}
|
||||
if (e) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
writing_ = false;
|
||||
writing_ = false;
|
||||
|
||||
do_write();
|
||||
});
|
||||
do_write();
|
||||
});
|
||||
|
||||
// No new asynchronous operations are started. This means that all
|
||||
// shared_ptr references to the connection object will disappear and
|
||||
|
|
Loading…
Reference in New Issue