diff --git a/src/Application.cpp b/src/Application.cpp index c4e12a263..96debe36b 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -32,7 +32,9 @@ #include "singletons/WindowManager.hpp" #include "util/IsBigEndian.hpp" #include "util/PostToThread.hpp" +#include "widgets/Notebook.hpp" #include "widgets/Window.hpp" +#include "widgets/splits/Split.hpp" namespace chatterino { @@ -78,13 +80,35 @@ void Application::initialize(Settings &settings, Paths &paths) assert(isAppInitialized == false); isAppInitialized = true; - Irc::getInstance().load(); + //Irc::getInstance().load(); for (auto &singleton : this->singletons_) { singleton->initialize(settings, paths); } + // add crash message + if (getArgs().crashRecovery) + { + if (auto selected = + this->windows->getMainWindow().getNotebook().getSelectedPage()) + { + if (auto container = dynamic_cast(selected)) + { + for (auto &&split : container->getSplits()) + { + if (auto channel = split->getChannel(); !channel->isEmpty()) + { + channel->addMessage(makeSystemMessage( + "Chatterino unexpectedly crashed and restarted. " + "You can disable automatic restarts in the " + "settings.")); + } + } + } + } + } + this->windows->updateWordTypeMask(); this->initNm(paths); diff --git a/src/RunGui.cpp b/src/RunGui.cpp index 190df9d5a..332a6f265 100644 --- a/src/RunGui.cpp +++ b/src/RunGui.cpp @@ -4,11 +4,14 @@ #include #include #include +#include +#include #include "Application.hpp" #include "common/NetworkManager.hpp" #include "singletons/Paths.hpp" #include "singletons/Resources.hpp" +#include "singletons/Settings.hpp" #include "singletons/Updates.hpp" #include "util/CombinePath.hpp" #include "widgets/dialogs/LastRunCrashDialog.hpp" @@ -21,12 +24,6 @@ # include #endif -// void initQt(); -// void installCustomPalette(); -// void showLastCrashDialog(); -// void createRunningFile(const QString &path); -// void removeRunningFile(const QString &path); - namespace chatterino { namespace { void installCustomPalette() @@ -109,13 +106,50 @@ namespace { { QFile::remove(path); } + + std::chrono::steady_clock::time_point signalsInitTime; + bool restartOnSignal = false; + + [[noreturn]] void handleSignal(int signum) + { + using namespace std::chrono_literals; + + // if (std::chrono::steady_clock::now() - signalsInitTime > 30s) + // { + QProcess proc; + proc.setProgram(QApplication::applicationFilePath()); + proc.setArguments({"--crash-recovery"}); + proc.startDetached(); + + // QProcess::startDetached(QApplication::applicationFilePath(), + // {"--crash-recovery"}); + // } + + _exit(signum); + } + + // We want to restart chatterino when it crashes and the setting is set to + // true. + void initSignalHandler() + { + //#if not defined(DEBUG) && not defined(_DEBUG) && not defined(NDEBUG) + signalsInitTime = std::chrono::steady_clock::now(); + + // signal(SIGINT, handleSignal); + signal(SIGSEGV, handleSignal); + // signal(SIGABRT_COMPAT, handleSignal); + //#endif + } } // namespace void runGui(QApplication &a, Paths &paths, Settings &settings) { initQt(); - initResources(); + initSignalHandler(); + + settings.restartOnCrash.connect( + [](const bool &value) { restartOnSignal = value; }); auto thread = std::thread([dir = paths.miscDirectory] { { diff --git a/src/main.cpp b/src/main.cpp index 7809a03e9..990f6e833 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,13 +1,14 @@ -#include "BrowserExtension.hpp" -#include "RunGui.hpp" -#include "singletons/Paths.hpp" -#include "singletons/Settings.hpp" -#include "util/IncognitoBrowser.hpp" - #include #include #include +#include "BrowserExtension.hpp" +#include "RunGui.hpp" +#include "common/Args.hpp" +#include "singletons/Paths.hpp" +#include "singletons/Settings.hpp" +#include "util/IncognitoBrowser.hpp" + using namespace chatterino; int main(int argc, char **argv) diff --git a/src/singletons/Settings.hpp b/src/singletons/Settings.hpp index a516cdd2a..76d645c35 100644 --- a/src/singletons/Settings.hpp +++ b/src/singletons/Settings.hpp @@ -1,15 +1,14 @@ #pragma once -#include "BaseSettings.hpp" +#include +#include +#include "BaseSettings.hpp" #include "common/Channel.hpp" #include "controllers/highlights/HighlightPhrase.hpp" #include "controllers/moderationactions/ModerationAction.hpp" #include "singletons/Toasts.hpp" -#include -#include - namespace chatterino { class Settings : public ABSettings @@ -213,6 +212,7 @@ public: BoolSetting openLinksIncognito = {"/misc/openLinksIncognito", 0}; QStringSetting cachePath = {"/cache/path", ""}; + BoolSetting restartOnCrash = {"/misc/restartOnCrash", true}; /// Debug BoolSetting showUnhandledIrcMessages = {"/debug/showUnhandledIrcMessages", diff --git a/src/singletons/WindowManager.cpp b/src/singletons/WindowManager.cpp index abafc90dc..ae5551619 100644 --- a/src/singletons/WindowManager.cpp +++ b/src/singletons/WindowManager.cpp @@ -1,5 +1,16 @@ #include "singletons/WindowManager.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "Application.hpp" #include "debug/AssertInGuiThread.hpp" #include "debug/Log.hpp" @@ -21,18 +32,6 @@ #include "widgets/splits/Split.hpp" #include "widgets/splits/SplitContainer.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - #define SETTINGS_FILENAME "/window-layout.json" namespace chatterino { @@ -556,8 +555,7 @@ void WindowManager::encodeNodeRecusively(SplitNode *node, QJsonObject &obj) { switch (node->getType()) { - case SplitNode::_Split: - { + case SplitNode::_Split: { obj.insert("type", "split"); obj.insert("moderationMode", node->getSplit()->getModerationMode()); QJsonObject split; @@ -568,8 +566,7 @@ void WindowManager::encodeNodeRecusively(SplitNode *node, QJsonObject &obj) } break; case SplitNode::HorizontalContainer: - case SplitNode::VerticalContainer: - { + case SplitNode::VerticalContainer: { obj.insert("type", node->getType() == SplitNode::HorizontalContainer ? "horizontal" : "vertical"); @@ -593,29 +590,24 @@ void WindowManager::encodeChannel(IndirectChannel channel, QJsonObject &obj) switch (channel.getType()) { - case Channel::Type::Twitch: - { + case Channel::Type::Twitch: { obj.insert("type", "twitch"); obj.insert("name", channel.get()->getName()); } break; - case Channel::Type::TwitchMentions: - { + case Channel::Type::TwitchMentions: { obj.insert("type", "mentions"); } break; - case Channel::Type::TwitchWatching: - { + case Channel::Type::TwitchWatching: { obj.insert("type", "watching"); } break; - case Channel::Type::TwitchWhispers: - { + case Channel::Type::TwitchWhispers: { obj.insert("type", "whispers"); } break; - case Channel::Type::Irc: - { + case Channel::Type::Irc: { if (auto ircChannel = dynamic_cast(channel.get().get())) { diff --git a/src/widgets/settingspages/GeneralPage.cpp b/src/widgets/settingspages/GeneralPage.cpp index 344933a81..101883851 100644 --- a/src/widgets/settingspages/GeneralPage.cpp +++ b/src/widgets/settingspages/GeneralPage.cpp @@ -303,6 +303,7 @@ void GeneralPage::initLayout(SettingsLayout &layout) #ifdef USEWINSDK layout.addCheckbox("Start with Windows", s.autorun); #endif + layout.addCheckbox("Restart on crash", s.restartOnCrash); layout.addTitle("Chat");