From 855f39b3219dec47fbf277ba01b7a4d3e3c2d2d4 Mon Sep 17 00:00:00 2001 From: pacevedom Date: Sun, 23 Dec 2018 18:02:33 +0100 Subject: [PATCH] Fix async object lifetimes --- src/asio_server_connection.h | 120 ++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 52 deletions(-) diff --git a/src/asio_server_connection.h b/src/asio_server_connection.h index 6be79406..e28bce0b 100644 --- a/src/asio_server_connection.h +++ b/src/asio_server_connection.h @@ -41,15 +41,15 @@ #include -#include #include +#include #include #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(args)...), - mux_(mux), + : socket_(std::forward(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( socket_.get_io_service(), socket_.lowest_layer().remote_endpoint(ec), - [this]() { do_write(); }, mux_); + [ this, self = this->shared_from_this() ]() { + if (!std::weak_ptr{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{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{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{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{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{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