fix some crashes, mostly related to network requests (#6187)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include "providers/recentmessages/Api.hpp"
|
||||
|
||||
#include "Application.hpp"
|
||||
#include "common/network/NetworkRequest.hpp"
|
||||
#include "common/network/NetworkResult.hpp"
|
||||
#include "common/QLogging.hpp"
|
||||
@@ -33,8 +34,15 @@ void load(
|
||||
|
||||
const long delayMs = jitter ? std::rand() % 100 : 0;
|
||||
QTimer::singleShot(delayMs, [=] {
|
||||
if (isAppAboutToQuit())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkRequest(url)
|
||||
.onSuccess([channelPtr, onLoaded](const auto &result) {
|
||||
assert(!isAppAboutToQuit());
|
||||
|
||||
auto shared = channelPtr.lock();
|
||||
if (!shared)
|
||||
{
|
||||
@@ -51,30 +59,33 @@ void load(
|
||||
auto builtMessages =
|
||||
buildRecentMessages(parsedMessages, shared.get());
|
||||
|
||||
postToThread([shared = std::move(shared),
|
||||
root = std::move(root),
|
||||
messages = std::move(builtMessages),
|
||||
onLoaded]() mutable {
|
||||
// Notify user about a possible gap in logs if it returned some messages
|
||||
// but isn't currently joined to a channel
|
||||
const auto errorCode = root.value("error_code").toString();
|
||||
if (!errorCode.isEmpty())
|
||||
{
|
||||
qCDebug(LOG)
|
||||
<< QString("Got error from API: error_code=%1, "
|
||||
"channel=%2")
|
||||
.arg(errorCode, shared->getName());
|
||||
if (errorCode == "channel_not_joined" &&
|
||||
!messages.empty())
|
||||
{
|
||||
shared->addSystemMessage(
|
||||
"Message history service recovering, there may "
|
||||
"be gaps in the message history.");
|
||||
}
|
||||
}
|
||||
postToThread(
|
||||
[shared = std::move(shared), root = std::move(root),
|
||||
messages = std::move(builtMessages), onLoaded]() mutable {
|
||||
assert(!isAppAboutToQuit());
|
||||
|
||||
onLoaded(messages);
|
||||
});
|
||||
// Notify user about a possible gap in logs if it returned some messages
|
||||
// but isn't currently joined to a channel
|
||||
const auto errorCode =
|
||||
root.value("error_code").toString();
|
||||
if (!errorCode.isEmpty())
|
||||
{
|
||||
qCDebug(LOG)
|
||||
<< QString("Got error from API: error_code=%1, "
|
||||
"channel=%2")
|
||||
.arg(errorCode, shared->getName());
|
||||
if (errorCode == "channel_not_joined" &&
|
||||
!messages.empty())
|
||||
{
|
||||
shared->addSystemMessage(
|
||||
"Message history service recovering, there "
|
||||
"may "
|
||||
"be gaps in the message history.");
|
||||
}
|
||||
}
|
||||
|
||||
onLoaded(messages);
|
||||
});
|
||||
})
|
||||
.onError([channelPtr, onError](const NetworkResult &result) {
|
||||
auto shared = channelPtr.lock();
|
||||
@@ -82,6 +93,7 @@ void load(
|
||||
{
|
||||
return;
|
||||
}
|
||||
assert(!isAppAboutToQuit());
|
||||
|
||||
qCDebug(LOG) << "Failed to load recent messages for"
|
||||
<< shared->getName();
|
||||
|
||||
@@ -440,6 +440,8 @@ void SeventvEmotes::getEmoteSet(
|
||||
getApp()->getSeventvAPI()->getEmoteSet(
|
||||
emoteSetId,
|
||||
[callback = std::move(successCallback), emoteSetId](const auto &json) {
|
||||
assert(!isAppAboutToQuit());
|
||||
|
||||
auto parsedEmotes = json["emotes"].toArray();
|
||||
|
||||
auto emoteMap = parseEmotes(parsedEmotes, false);
|
||||
|
||||
@@ -106,13 +106,13 @@ ChannelPointReward::ChannelPointReward(const QJsonObject &redemption)
|
||||
}
|
||||
else
|
||||
{
|
||||
static const ImageSet defaultImage{
|
||||
static const ImageSet *defaultImage = new ImageSet{
|
||||
Image::fromUrl({twitchChannelPointRewardUrl("1.png")}, 1, baseSize),
|
||||
Image::fromUrl({twitchChannelPointRewardUrl("2.png")}, 0.5,
|
||||
baseSize * 2),
|
||||
Image::fromUrl({twitchChannelPointRewardUrl("4.png")}, 0.25,
|
||||
baseSize * 4)};
|
||||
this->image = defaultImage;
|
||||
this->image = *defaultImage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1381,6 +1381,7 @@ void TwitchChannel::loadRecentMessages()
|
||||
recentmessages::load(
|
||||
this->getName(), weak,
|
||||
[weak](const auto &messages) {
|
||||
assert(!isAppAboutToQuit());
|
||||
auto shared = weak.lock();
|
||||
if (!shared)
|
||||
{
|
||||
|
||||
@@ -254,6 +254,11 @@ void TwitchIrcServer::initialize()
|
||||
auto reward = ChannelPointReward(data);
|
||||
|
||||
postToThread([chan, reward] {
|
||||
if (isAppAboutToQuit())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto *channel = dynamic_cast<TwitchChannel *>(chan.get()))
|
||||
{
|
||||
channel->addChannelPointReward(reward);
|
||||
@@ -262,6 +267,13 @@ void TwitchIrcServer::initialize()
|
||||
});
|
||||
}
|
||||
|
||||
void TwitchIrcServer::aboutToQuit()
|
||||
{
|
||||
this->signalHolder.clear();
|
||||
|
||||
this->channels.clear();
|
||||
}
|
||||
|
||||
void TwitchIrcServer::initializeConnection(IrcConnection *connection,
|
||||
ConnectionType type)
|
||||
{
|
||||
@@ -550,8 +562,8 @@ std::shared_ptr<Channel> TwitchIrcServer::getCustomChannel(
|
||||
return this->automodChannel;
|
||||
}
|
||||
|
||||
static auto getTimer = [](ChannelPtr channel, int msBetweenMessages,
|
||||
bool addInitialMessages) {
|
||||
static auto getTimer = [this](ChannelPtr channel, int msBetweenMessages,
|
||||
bool addInitialMessages) {
|
||||
if (addInitialMessages)
|
||||
{
|
||||
for (auto i = 0; i < 1000; i++)
|
||||
@@ -561,7 +573,7 @@ std::shared_ptr<Channel> TwitchIrcServer::getCustomChannel(
|
||||
}
|
||||
|
||||
auto *timer = new QTimer;
|
||||
QObject::connect(timer, &QTimer::timeout, [channel] {
|
||||
QObject::connect(timer, &QTimer::timeout, this, [channel] {
|
||||
channel->addSystemMessage(QTime::currentTime().toString());
|
||||
});
|
||||
timer->start(msBetweenMessages);
|
||||
@@ -841,37 +853,43 @@ void TwitchIrcServer::initEventAPIs(BttvLiveUpdates *bttvLiveUpdates,
|
||||
bttvLiveUpdates->signals_.emoteAdded, [&](const auto &data) {
|
||||
auto chan = this->getChannelOrEmptyByID(data.channelID);
|
||||
|
||||
postToThread([chan, data] {
|
||||
if (auto *channel =
|
||||
dynamic_cast<TwitchChannel *>(chan.get()))
|
||||
{
|
||||
channel->addBttvEmote(data);
|
||||
}
|
||||
});
|
||||
postToThread(
|
||||
[chan, data] {
|
||||
if (auto *channel =
|
||||
dynamic_cast<TwitchChannel *>(chan.get()))
|
||||
{
|
||||
channel->addBttvEmote(data);
|
||||
}
|
||||
},
|
||||
this);
|
||||
});
|
||||
this->signalHolder.managedConnect(
|
||||
bttvLiveUpdates->signals_.emoteUpdated, [&](const auto &data) {
|
||||
auto chan = this->getChannelOrEmptyByID(data.channelID);
|
||||
|
||||
postToThread([chan, data] {
|
||||
if (auto *channel =
|
||||
dynamic_cast<TwitchChannel *>(chan.get()))
|
||||
{
|
||||
channel->updateBttvEmote(data);
|
||||
}
|
||||
});
|
||||
postToThread(
|
||||
[chan, data] {
|
||||
if (auto *channel =
|
||||
dynamic_cast<TwitchChannel *>(chan.get()))
|
||||
{
|
||||
channel->updateBttvEmote(data);
|
||||
}
|
||||
},
|
||||
this);
|
||||
});
|
||||
this->signalHolder.managedConnect(
|
||||
bttvLiveUpdates->signals_.emoteRemoved, [&](const auto &data) {
|
||||
auto chan = this->getChannelOrEmptyByID(data.channelID);
|
||||
|
||||
postToThread([chan, data] {
|
||||
if (auto *channel =
|
||||
dynamic_cast<TwitchChannel *>(chan.get()))
|
||||
{
|
||||
channel->removeBttvEmote(data);
|
||||
}
|
||||
});
|
||||
postToThread(
|
||||
[chan, data] {
|
||||
if (auto *channel =
|
||||
dynamic_cast<TwitchChannel *>(chan.get()))
|
||||
{
|
||||
channel->removeBttvEmote(data);
|
||||
}
|
||||
},
|
||||
this);
|
||||
});
|
||||
|
||||
bttvLiveUpdates->start();
|
||||
@@ -886,30 +904,36 @@ void TwitchIrcServer::initEventAPIs(BttvLiveUpdates *bttvLiveUpdates,
|
||||
{
|
||||
this->signalHolder.managedConnect(
|
||||
seventvEventAPI->signals_.emoteAdded, [this](const auto &data) {
|
||||
postToThread([this, data] {
|
||||
this->forEachSeventvEmoteSet(data.emoteSetID,
|
||||
[data](TwitchChannel &chan) {
|
||||
chan.addSeventvEmote(data);
|
||||
});
|
||||
});
|
||||
postToThread(
|
||||
[this, data] {
|
||||
this->forEachSeventvEmoteSet(
|
||||
data.emoteSetID, [data](TwitchChannel &chan) {
|
||||
chan.addSeventvEmote(data);
|
||||
});
|
||||
},
|
||||
this);
|
||||
});
|
||||
this->signalHolder.managedConnect(
|
||||
seventvEventAPI->signals_.emoteUpdated, [this](const auto &data) {
|
||||
postToThread([this, data] {
|
||||
this->forEachSeventvEmoteSet(
|
||||
data.emoteSetID, [data](TwitchChannel &chan) {
|
||||
chan.updateSeventvEmote(data);
|
||||
});
|
||||
});
|
||||
postToThread(
|
||||
[this, data] {
|
||||
this->forEachSeventvEmoteSet(
|
||||
data.emoteSetID, [data](TwitchChannel &chan) {
|
||||
chan.updateSeventvEmote(data);
|
||||
});
|
||||
},
|
||||
this);
|
||||
});
|
||||
this->signalHolder.managedConnect(
|
||||
seventvEventAPI->signals_.emoteRemoved, [this](const auto &data) {
|
||||
postToThread([this, data] {
|
||||
this->forEachSeventvEmoteSet(
|
||||
data.emoteSetID, [data](TwitchChannel &chan) {
|
||||
chan.removeSeventvEmote(data);
|
||||
});
|
||||
});
|
||||
postToThread(
|
||||
[this, data] {
|
||||
this->forEachSeventvEmoteSet(
|
||||
data.emoteSetID, [data](TwitchChannel &chan) {
|
||||
chan.removeSeventvEmote(data);
|
||||
});
|
||||
},
|
||||
this);
|
||||
});
|
||||
this->signalHolder.managedConnect(
|
||||
seventvEventAPI->signals_.userUpdated, [this](const auto &data) {
|
||||
|
||||
@@ -94,6 +94,8 @@ public:
|
||||
|
||||
void initialize();
|
||||
|
||||
void aboutToQuit();
|
||||
|
||||
void forEachChannelAndSpecialChannels(
|
||||
std::function<void(ChannelPtr)> func) override;
|
||||
|
||||
|
||||
@@ -75,6 +75,11 @@ void Connection::onNotification(const lib::messages::Metadata &metadata,
|
||||
void Connection::onClose(std::unique_ptr<lib::Listener> self,
|
||||
const std::optional<std::string> &reconnectURL)
|
||||
{
|
||||
if (isAppAboutToQuit())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto *app = tryGetApp();
|
||||
if (!app)
|
||||
{
|
||||
|
||||
@@ -104,7 +104,10 @@ Controller::~Controller()
|
||||
connection->close();
|
||||
}
|
||||
|
||||
this->subscriptions.clear();
|
||||
{
|
||||
std::lock_guard lock(this->subscriptionsMutex);
|
||||
this->subscriptions.clear();
|
||||
}
|
||||
|
||||
this->work.reset();
|
||||
|
||||
@@ -341,7 +344,7 @@ void Controller::subscribe(const SubscriptionRequest &request, bool isRetry)
|
||||
qCDebug(LOG) << "Make helix request for" << request;
|
||||
getHelix()->createEventSubSubscription(
|
||||
request, listener->getSessionID(),
|
||||
[this, request, connection,
|
||||
[this, request,
|
||||
weakConnection{std::weak_ptr<lib::Session>(connection)}](
|
||||
const auto &res) {
|
||||
qCDebug(LOG) << "Subscription success" << request;
|
||||
@@ -507,6 +510,12 @@ void Controller::registerConnection(std::weak_ptr<lib::Session> &&connection)
|
||||
|
||||
void Controller::retrySubscription(const SubscriptionRequest &request)
|
||||
{
|
||||
if (isAppAboutToQuit())
|
||||
{
|
||||
qCDebug(LOG) << "retrySubscription, but app is quitting" << request;
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard lock(this->subscriptionsMutex);
|
||||
|
||||
auto &subscription = this->subscriptions[request];
|
||||
@@ -536,6 +545,14 @@ void Controller::retrySubscription(const SubscriptionRequest &request)
|
||||
std::make_unique<boost::asio::system_timer>(this->ioContext);
|
||||
retryTimer->expires_after(subscription.backoff.next() + jitter);
|
||||
retryTimer->async_wait([this, request](const auto &ec) {
|
||||
if (isAppAboutToQuit())
|
||||
{
|
||||
qCDebug(LOG)
|
||||
<< "Retry was going to fire, but app is quitting so we won't."
|
||||
<< request;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ec)
|
||||
{
|
||||
qCDebug(LOG) << "Firing retry" << request;
|
||||
|
||||
Reference in New Issue
Block a user