mirror of
https://github.com/Icinga/icinga2.git
synced 2025-07-23 05:34:48 +02:00
Merge pull request #7487 from Icinga/bugfix/http-api-shutdown-avoid-io
API: Avoid I/O on shutdown
This commit is contained in:
commit
9e16502581
@ -21,10 +21,12 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <boost/asio/error.hpp>
|
||||||
#include <boost/asio/io_service.hpp>
|
#include <boost/asio/io_service.hpp>
|
||||||
#include <boost/asio/spawn.hpp>
|
#include <boost/asio/spawn.hpp>
|
||||||
#include <boost/beast/core.hpp>
|
#include <boost/beast/core.hpp>
|
||||||
#include <boost/beast/http.hpp>
|
#include <boost/beast/http.hpp>
|
||||||
|
#include <boost/system/error_code.hpp>
|
||||||
#include <boost/system/system_error.hpp>
|
#include <boost/system/system_error.hpp>
|
||||||
#include <boost/thread/once.hpp>
|
#include <boost/thread/once.hpp>
|
||||||
|
|
||||||
@ -88,13 +90,13 @@ void HttpServerConnection::Disconnect()
|
|||||||
*/
|
*/
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
m_Stream->next_layer().async_shutdown(yc[ec]);
|
m_CheckLivenessTimer.cancel();
|
||||||
|
|
||||||
m_Stream->lowest_layer().shutdown(m_Stream->lowest_layer().shutdown_both, ec);
|
|
||||||
|
|
||||||
m_Stream->lowest_layer().cancel(ec);
|
m_Stream->lowest_layer().cancel(ec);
|
||||||
|
|
||||||
m_CheckLivenessTimer.cancel();
|
m_Stream->next_layer().async_shutdown(yc[ec]);
|
||||||
|
|
||||||
|
m_Stream->lowest_layer().shutdown(m_Stream->lowest_layer().shutdown_both, ec);
|
||||||
|
|
||||||
auto listener (ApiListener::GetInstance());
|
auto listener (ApiListener::GetInstance());
|
||||||
|
|
||||||
@ -141,11 +143,15 @@ bool EnsureValidHeaders(
|
|||||||
boost::beast::flat_buffer& buf,
|
boost::beast::flat_buffer& buf,
|
||||||
boost::beast::http::parser<true, boost::beast::http::string_body>& parser,
|
boost::beast::http::parser<true, boost::beast::http::string_body>& parser,
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
boost::beast::http::response<boost::beast::http::string_body>& response,
|
||||||
|
bool& shuttingDown,
|
||||||
boost::asio::yield_context& yc
|
boost::asio::yield_context& yc
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
namespace http = boost::beast::http;
|
namespace http = boost::beast::http;
|
||||||
|
|
||||||
|
if (shuttingDown)
|
||||||
|
return false;
|
||||||
|
|
||||||
bool httpError = false;
|
bool httpError = false;
|
||||||
String errorMsg;
|
String errorMsg;
|
||||||
|
|
||||||
@ -154,16 +160,19 @@ bool EnsureValidHeaders(
|
|||||||
http::async_read_header(stream, buf, parser, yc[ec]);
|
http::async_read_header(stream, buf, parser, yc[ec]);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
|
if (ec == boost::asio::error::operation_aborted)
|
||||||
|
return false;
|
||||||
|
|
||||||
errorMsg = ec.message();
|
errorMsg = ec.message();
|
||||||
httpError = true;
|
httpError = true;
|
||||||
}
|
} else {
|
||||||
|
switch (parser.get().version()) {
|
||||||
switch (parser.get().version()) {
|
case 10:
|
||||||
case 10:
|
case 11:
|
||||||
case 11:
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
errorMsg = "Unsupported HTTP version";
|
||||||
errorMsg = "Unsupported HTTP version";
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!errorMsg.IsEmpty() || httpError) {
|
if (!errorMsg.IsEmpty() || httpError) {
|
||||||
@ -343,6 +352,7 @@ bool EnsureValidBody(
|
|||||||
boost::beast::http::parser<true, boost::beast::http::string_body>& parser,
|
boost::beast::http::parser<true, boost::beast::http::string_body>& parser,
|
||||||
ApiUser::Ptr& authenticatedUser,
|
ApiUser::Ptr& authenticatedUser,
|
||||||
boost::beast::http::response<boost::beast::http::string_body>& response,
|
boost::beast::http::response<boost::beast::http::string_body>& response,
|
||||||
|
bool& shuttingDown,
|
||||||
boost::asio::yield_context& yc
|
boost::asio::yield_context& yc
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -385,11 +395,17 @@ bool EnsureValidBody(
|
|||||||
parser.body_limit(maxSize);
|
parser.body_limit(maxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shuttingDown)
|
||||||
|
return false;
|
||||||
|
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
http::async_read(stream, buf, parser, yc[ec]);
|
http::async_read(stream, buf, parser, yc[ec]);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
|
if (ec == boost::asio::error::operation_aborted)
|
||||||
|
return false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unfortunately there's no way to tell an HTTP protocol error
|
* Unfortunately there's no way to tell an HTTP protocol error
|
||||||
* from an error on a lower layer:
|
* from an error on a lower layer:
|
||||||
@ -443,6 +459,12 @@ bool ProcessRequest(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto sysErr (dynamic_cast<const boost::system::system_error*>(&ex));
|
||||||
|
|
||||||
|
if (sysErr && sysErr->code() == boost::asio::error::operation_aborted) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
http::response<http::string_body> response;
|
http::response<http::string_body> response;
|
||||||
|
|
||||||
HttpUtility::SendJsonError(response, nullptr, 500, "Unhandled exception" , DiagnosticInformation(ex));
|
HttpUtility::SendJsonError(response, nullptr, 500, "Unhandled exception" , DiagnosticInformation(ex));
|
||||||
@ -488,7 +510,7 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
|
|||||||
|
|
||||||
// Best practice is to always reset the buffer.
|
// Best practice is to always reset the buffer.
|
||||||
buf = {};
|
buf = {};
|
||||||
if (!EnsureValidHeaders(*m_Stream, buf, parser, response, yc)) {
|
if (!EnsureValidHeaders(*m_Stream, buf, parser, response, m_ShuttingDown, yc)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -535,7 +557,7 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
|
|||||||
|
|
||||||
// Best practice is to always reset the buffer.
|
// Best practice is to always reset the buffer.
|
||||||
buf = {};
|
buf = {};
|
||||||
if (!EnsureValidBody(*m_Stream, buf, parser, authenticatedUser, response, yc)) {
|
if (!EnsureValidBody(*m_Stream, buf, parser, authenticatedUser, response, m_ShuttingDown, yc)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,14 +224,14 @@ void JsonRpcConnection::Disconnect()
|
|||||||
*/
|
*/
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
m_Stream->next_layer().async_shutdown(yc[ec]);
|
m_CheckLivenessTimer.cancel();
|
||||||
|
m_HeartbeatTimer.cancel();
|
||||||
m_Stream->lowest_layer().shutdown(m_Stream->lowest_layer().shutdown_both, ec);
|
|
||||||
|
|
||||||
m_Stream->lowest_layer().cancel(ec);
|
m_Stream->lowest_layer().cancel(ec);
|
||||||
|
|
||||||
m_CheckLivenessTimer.cancel();
|
m_Stream->next_layer().async_shutdown(yc[ec]);
|
||||||
m_HeartbeatTimer.cancel();
|
|
||||||
|
m_Stream->lowest_layer().shutdown(m_Stream->lowest_layer().shutdown_both, ec);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user