diff options
| author | Dan Engelbrecht <[email protected]> | 2023-05-11 10:52:14 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-05-11 10:52:14 +0200 |
| commit | 0049b60faea2b14f77a263b326a415c94cf4bad3 (patch) | |
| tree | 44c50579f116d53668123224bd26c218938fed83 /src/zenhttp/httpasio.cpp | |
| parent | ZEN_LOG_SCOPE compile fix (diff) | |
| download | zen-0049b60faea2b14f77a263b326a415c94cf4bad3.tar.xz zen-0049b60faea2b14f77a263b326a415c94cf4bad3.zip | |
Close down http server gracefully when exiting even while requests are still being processed (#290)
* Close down http server gracefully when exiting even while requests are still being processed
Diffstat (limited to 'src/zenhttp/httpasio.cpp')
| -rw-r--r-- | src/zenhttp/httpasio.cpp | 58 |
1 files changed, 48 insertions, 10 deletions
diff --git a/src/zenhttp/httpasio.cpp b/src/zenhttp/httpasio.cpp index 79b2c0a3d..7149caf28 100644 --- a/src/zenhttp/httpasio.cpp +++ b/src/zenhttp/httpasio.cpp @@ -329,7 +329,7 @@ private: void EnqueueRead(); void OnDataReceived(const asio::error_code& Ec, std::size_t ByteCount); void OnResponseDataSent(const asio::error_code& Ec, std::size_t ByteCount, bool Pop = false); - void OnError(); + void CloseConnection(); HttpAsioServerImpl& m_Server; asio::streambuf m_RequestBuffer; @@ -368,9 +368,17 @@ HttpServerConnection::HandleNewRequest() void HttpServerConnection::TerminateConnection() { + if (m_RequestState == RequestState::kDone || m_RequestState == RequestState::kTerminated) + { + return; + } + m_RequestState = RequestState::kTerminated; + ZEN_ASSERT(m_Socket); + // Terminating, we don't care about any errors when closing socket std::error_code Ec; + m_Socket->shutdown(asio::socket_base::shutdown_both, Ec); m_Socket->close(Ec); } @@ -407,7 +415,7 @@ HttpServerConnection::OnDataReceived(const asio::error_code& Ec, [[maybe_unused] else { ZEN_WARN("on data received ERROR, connection '{}' reason '{}'", m_ConnectionId, Ec.message()); - return OnError(); + return TerminateConnection(); } } @@ -424,7 +432,7 @@ HttpServerConnection::OnDataReceived(const asio::error_code& Ec, [[maybe_unused] size_t Result = m_RequestData.ConsumeData((const char*)InputBuffer.data(), InputBuffer.size()); if (Result == ~0ull) { - return OnError(); + return TerminateConnection(); } m_RequestBuffer.consume(Result); @@ -449,7 +457,7 @@ HttpServerConnection::OnResponseDataSent(const asio::error_code& Ec, [[maybe_unu if (Ec) { ZEN_WARN("on data sent ERROR, connection '{}' reason '{}'", m_ConnectionId, Ec.message()); - OnError(); + TerminateConnection(); } else { @@ -461,9 +469,7 @@ HttpServerConnection::OnResponseDataSent(const asio::error_code& Ec, [[maybe_unu if (!m_RequestData.IsKeepAlive()) { - m_RequestState = RequestState::kDone; - - m_Socket->close(); + CloseConnection(); } else { @@ -479,9 +485,26 @@ HttpServerConnection::OnResponseDataSent(const asio::error_code& Ec, [[maybe_unu } void -HttpServerConnection::OnError() +HttpServerConnection::CloseConnection() { - m_Socket->close(); + if (m_RequestState == RequestState::kDone || m_RequestState == RequestState::kTerminated) + { + return; + } + ZEN_ASSERT(m_Socket); + m_RequestState = RequestState::kDone; + + std::error_code Ec; + m_Socket->shutdown(asio::socket_base::shutdown_receive, Ec); + if (Ec) + { + ZEN_WARN("socket shutdown ERROR, reason '{}'", Ec.message()); + } + m_Socket->close(Ec); + if (Ec) + { + ZEN_WARN("socket close ERROR, reason '{}'", Ec.message()); + } } void @@ -1053,7 +1076,12 @@ struct HttpAcceptor } else { - m_Acceptor.close(); + std::error_code CloseEc; + m_Acceptor.close(CloseEc); + if (CloseEc) + { + ZEN_WARN("acceptor close ERROR, reason '{}'", CloseEc.message()); + } } }); } @@ -1296,6 +1324,15 @@ HttpAsioServer::HttpAsioServer() : m_Impl(std::make_unique<asio_http::HttpAsioSe HttpAsioServer::~HttpAsioServer() { + if (m_Impl) + { + ZEN_ERROR("~HttpAsioServer() called without calling Close() first"); + } +} + +void +HttpAsioServer::Close() +{ try { m_Impl->Stop(); @@ -1304,6 +1341,7 @@ HttpAsioServer::~HttpAsioServer() { ZEN_WARN("Caught exception stopping http asio server: {}", ex.what()); } + m_Impl.reset(); } void |