fix(eventsub): add timeout to close operation (#6645)
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
This commit is contained in:
@@ -38,6 +38,7 @@
|
|||||||
- Bugfix: Fixed middle-clicking usernames in a local channel opening an invalid viewercard. (#6577)
|
- Bugfix: Fixed middle-clicking usernames in a local channel opening an invalid viewercard. (#6577)
|
||||||
- Bugfix: Added `desktop-entry` hint to Linux notifications. (#6615)
|
- Bugfix: Added `desktop-entry` hint to Linux notifications. (#6615)
|
||||||
- Bugfix: Fixed <kbd>CMD</kbd> + <kbd>DELETE</kbd> behavior in the user notes editing dialog for macOS. (#6676)
|
- Bugfix: Fixed <kbd>CMD</kbd> + <kbd>DELETE</kbd> behavior in the user notes editing dialog for macOS. (#6676)
|
||||||
|
- Bugfix: Fixed a potential crash when closing Chatterino with a slow network connection. (#6645)
|
||||||
- Dev: Update release documentation. (#6498)
|
- Dev: Update release documentation. (#6498)
|
||||||
- Dev: Make code sanitizers opt in with the `CHATTERINO_SANITIZER_SUPPORT` CMake option. After that's enabled, use the `SANITIZE_*` flag to enable individual sanitizers. (#6493)
|
- Dev: Make code sanitizers opt in with the `CHATTERINO_SANITIZER_SUPPORT` CMake option. After that's enabled, use the `SANITIZE_*` flag to enable individual sanitizers. (#6493)
|
||||||
- Dev: Remove unused QTextCodec includes. (#6487)
|
- Dev: Remove unused QTextCodec includes. (#6487)
|
||||||
|
|||||||
@@ -81,6 +81,9 @@ private:
|
|||||||
std::chrono::seconds keepaliveTimeout{0};
|
std::chrono::seconds keepaliveTimeout{0};
|
||||||
bool receivedMessage = false;
|
bool receivedMessage = false;
|
||||||
std::unique_ptr<boost::asio::system_timer> keepaliveTimer;
|
std::unique_ptr<boost::asio::system_timer> keepaliveTimer;
|
||||||
|
|
||||||
|
boost::asio::cancellation_signal closeSignal;
|
||||||
|
boost::asio::steady_timer closeTimeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace chatterino::eventsub::lib
|
} // namespace chatterino::eventsub::lib
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ target_link_libraries(${PROJECT_NAME}
|
|||||||
target_compile_definitions(${PROJECT_NAME} PUBLIC
|
target_compile_definitions(${PROJECT_NAME} PUBLIC
|
||||||
$<$<BOOL:${MSVC}>:BOOST_JSON_NO_LIB>
|
$<$<BOOL:${MSVC}>:BOOST_JSON_NO_LIB>
|
||||||
$<$<BOOL:${MSVC}>:BOOST_CONTAINER_NO_LIB>
|
$<$<BOOL:${MSVC}>:BOOST_CONTAINER_NO_LIB>
|
||||||
|
QT_NO_KEYWORDS
|
||||||
)
|
)
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
|
|||||||
@@ -249,6 +249,7 @@ Session::Session(boost::asio::io_context &ioc, boost::asio::ssl::context &ctx,
|
|||||||
, resolver(boost::asio::make_strand(ioc))
|
, resolver(boost::asio::make_strand(ioc))
|
||||||
, ws(boost::asio::make_strand(ioc), ctx)
|
, ws(boost::asio::make_strand(ioc), ctx)
|
||||||
, listener(std::move(listener))
|
, listener(std::move(listener))
|
||||||
|
, closeTimeout(this->ws.get_executor())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,10 +273,30 @@ void Session::close()
|
|||||||
{
|
{
|
||||||
boost::beast::websocket::close_reason closeReason("Shutting down");
|
boost::beast::websocket::close_reason closeReason("Shutting down");
|
||||||
|
|
||||||
|
// cancel all pending operations
|
||||||
|
this->keepaliveTimer.reset();
|
||||||
|
this->resolver.cancel();
|
||||||
|
beast::get_lowest_layer(this->ws).cancel();
|
||||||
|
|
||||||
|
// set a timeout on the async_close() call
|
||||||
|
this->closeTimeout.expires_after(std::chrono::milliseconds(200));
|
||||||
|
this->closeTimeout.async_wait(
|
||||||
|
[self = this->shared_from_this()](boost::system::error_code ec) {
|
||||||
|
if (ec == boost::asio::error::operation_aborted)
|
||||||
|
{
|
||||||
|
return; // we're aborted by onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
self->log->warn("Close timed out.");
|
||||||
|
self->closeSignal.emit(boost::asio::cancellation_type::total);
|
||||||
|
});
|
||||||
|
|
||||||
// TODO: Test this with a misbehaving eventsub server that doesn't respond to our close
|
// TODO: Test this with a misbehaving eventsub server that doesn't respond to our close
|
||||||
this->ws.async_close(
|
this->ws.async_close(
|
||||||
closeReason,
|
closeReason,
|
||||||
beast::bind_front_handler(&Session::onClose, shared_from_this()));
|
boost::asio::bind_cancellation_slot(
|
||||||
|
this->closeSignal.slot(),
|
||||||
|
beast::bind_front_handler(&Session::onClose, shared_from_this())));
|
||||||
}
|
}
|
||||||
|
|
||||||
Listener *Session::getListener()
|
Listener *Session::getListener()
|
||||||
@@ -381,7 +402,7 @@ void Session::onRead(beast::error_code ec, std::size_t bytes_transferred)
|
|||||||
{
|
{
|
||||||
boost::ignore_unused(bytes_transferred);
|
boost::ignore_unused(bytes_transferred);
|
||||||
|
|
||||||
if (!this->listener)
|
if (!this->listener || ec == boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -418,7 +439,7 @@ void Session::onRead(beast::error_code ec, std::size_t bytes_transferred)
|
|||||||
*/
|
*/
|
||||||
void Session::onClose(beast::error_code ec)
|
void Session::onClose(beast::error_code ec)
|
||||||
{
|
{
|
||||||
if (ec)
|
if (ec && ec != boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
this->fail(ec, "close");
|
this->fail(ec, "close");
|
||||||
return;
|
return;
|
||||||
@@ -427,6 +448,7 @@ void Session::onClose(beast::error_code ec)
|
|||||||
// If we get here then the connection is closed gracefully
|
// If we get here then the connection is closed gracefully
|
||||||
if (this->listener)
|
if (this->listener)
|
||||||
{
|
{
|
||||||
|
this->closeTimeout.cancel();
|
||||||
this->listener->onClose(std::move(this->listener), {});
|
this->listener->onClose(std::move(this->listener), {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -441,6 +463,7 @@ void Session::fail(beast::error_code ec, std::string_view op)
|
|||||||
{
|
{
|
||||||
this->keepaliveTimer.reset();
|
this->keepaliveTimer.reset();
|
||||||
}
|
}
|
||||||
|
this->closeTimeout.cancel();
|
||||||
|
|
||||||
this->listener->onClose(std::move(this->listener), {});
|
this->listener->onClose(std::move(this->listener), {});
|
||||||
}
|
}
|
||||||
@@ -589,7 +612,7 @@ void Session::checkKeepalive()
|
|||||||
this->keepaliveTimer->async_wait(
|
this->keepaliveTimer->async_wait(
|
||||||
[weak{this->weak_from_this()}](boost::system::error_code ec) {
|
[weak{this->weak_from_this()}](boost::system::error_code ec) {
|
||||||
auto strong = weak.lock();
|
auto strong = weak.lock();
|
||||||
if (!strong)
|
if (!strong || ec == boost::asio::error::operation_aborted)
|
||||||
{
|
{
|
||||||
// Session was destroyed
|
// Session was destroyed
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user