From 6459840507761abe447282750fbfc64f448c94f9 Mon Sep 17 00:00:00 2001 From: Romain Le Jeune Date: Fri, 20 Jan 2023 07:43:02 +0000 Subject: [PATCH] GODT-2253: Restart Launcher from the gui when GUI crashes. --- .../bridge-gui/bridge-gui/AppController.cpp | 22 +++++++++++++++++++ .../bridge-gui/bridge-gui/AppController.h | 4 ++++ .../bridge-gui/bridge-gui/CommandLine.cpp | 3 +++ .../bridge-gui/bridge-gui/CommandLine.h | 1 + .../frontend/bridge-gui/bridge-gui/main.cpp | 8 ++++++- 5 files changed, 37 insertions(+), 1 deletion(-) diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp index 89c9bf31..6b69b4d1 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp @@ -28,6 +28,9 @@ using namespace bridgepp; +namespace { +QString const noWindowFlag = "--no-window"; ///< The no-window command-line flag. +} //**************************************************************************************************************************************************** /// \return The AppController instance. @@ -75,6 +78,25 @@ void AppController::onFatalError(QString const &function, QString const &message QString const fullMessage = QString("%1(): %2").arg(function, message); reportSentryException(SENTRY_LEVEL_ERROR, "AppController got notified of a fatal error", "Exception", fullMessage.toLocal8Bit()); QMessageBox::critical(nullptr, tr("Error"), message); + restart(true); log().fatal(fullMessage); qApp->exit(EXIT_FAILURE); } + +void AppController::restart(bool isCrashing) { + if (!launcher_.isEmpty()) { + QProcess p; + log_->info(QString("Restarting - App : %1 - Args : %2").arg(launcher_,launcherArgs_.join(" "))); + QStringList args = launcherArgs_; + if (isCrashing) + args.append(noWindowFlag); + + p.startDetached(launcher_, args); + p.waitForStarted(); + } +} + +void AppController::setLauncherArgs(const QString& launcher, const QStringList& args){ + launcher_ = launcher; + launcherArgs_ = args; +} \ No newline at end of file diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.h b/internal/frontend/bridge-gui/bridge-gui/AppController.h index 8049516e..224857c1 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.h +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.h @@ -55,18 +55,22 @@ public: // member functions. bridgepp::Log &log() { return *log_; } ///< Return a reference to the log. std::unique_ptr &bridgeOverseer() { return bridgeOverseer_; }; ///< Returns a reference the bridge overseer bridgepp::ProcessMonitor *bridgeMonitor() const; ///< Return the bridge worker. + void setLauncherArgs(const QString& launcher, const QStringList& args); public slots: void onFatalError(QString const &function, QString const &message); ///< Handle fatal errors. private: // member functions AppController(); ///< Default constructor. + void restart(bool isCrashing = false); ///< Restart the app. private: // data members std::unique_ptr backend_; ///< The backend. std::unique_ptr grpc_; ///< The RPC client. std::unique_ptr log_; ///< The log. std::unique_ptr bridgeOverseer_; ///< The overseer for the bridge monitor worker. + QString launcher_; + QStringList launcherArgs_; }; diff --git a/internal/frontend/bridge-gui/bridge-gui/CommandLine.cpp b/internal/frontend/bridge-gui/bridge-gui/CommandLine.cpp index 412f4659..5a892da0 100644 --- a/internal/frontend/bridge-gui/bridge-gui/CommandLine.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/CommandLine.cpp @@ -98,6 +98,7 @@ CommandLineOptions parseCommandLine(int argc, char *argv[]) { // we can't use QCommandLineParser here since it will fail on unknown options. // Arguments may contain some bridge flags. if (arg == softwareRendererFlag) { + options.bridgeGuiArgs.append(arg); options.useSoftwareRenderer = true; } if (arg == noWindowFlag) { @@ -113,10 +114,12 @@ CommandLineOptions parseCommandLine(int argc, char *argv[]) { else if (arg == "--attach" || arg == "-a") { // we don't keep the attach mode within the args since we don't need it for Bridge. options.attach = true; + options.bridgeGuiArgs.append(arg); } #endif else { options.bridgeArgs.append(arg); + options.bridgeGuiArgs.append(arg); } } if (!flagFound) { diff --git a/internal/frontend/bridge-gui/bridge-gui/CommandLine.h b/internal/frontend/bridge-gui/bridge-gui/CommandLine.h index 2d0d3af6..9accfee8 100644 --- a/internal/frontend/bridge-gui/bridge-gui/CommandLine.h +++ b/internal/frontend/bridge-gui/bridge-gui/CommandLine.h @@ -28,6 +28,7 @@ //**************************************************************************************************************************************************** struct CommandLineOptions { QStringList bridgeArgs; ///< The command-line arguments we will pass to bridge when launching it. + QStringList bridgeGuiArgs; ///< The command-line arguments we will pass to bridge when launching it. QString launcher; ///< The path to the launcher. bool attach { false }; ///< Is the application running in attached mode? bridgepp::Log::Level logLevel { bridgepp::Log::defaultLevel }; ///< The log level diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 51c0411c..47a75a28 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -55,6 +55,7 @@ QString const bridgeLock = "bridge-v3.lock"; ///< The file name used for the bri QString const bridgeGUILock = "bridge-v3-gui.lock"; ///< The file name used for the bridge-gui lock file. QString const exeName = "bridge" + exeSuffix; ///< The bridge executable file name.* qint64 const grpcServiceConfigWaitDelayMs = 180000; ///< The wait delay for the gRPC config file in milliseconds. +QString const waitFlag = "--wait"; ///< The wait command-line flag. } // anonymous namespace @@ -398,7 +399,12 @@ int main(int argc, char *argv[]) { int result = 0; if (!startError) { // we succeeded in launching bridge, so we can be set as mainExecutable. - app().grpc().setMainExecutable(QString::fromLocal8Bit(argv[0])); + QString mainexec = QString::fromLocal8Bit(argv[0]); + app().grpc().setMainExecutable(mainexec); + QStringList args = cliOptions.bridgeGuiArgs; + args.append(waitFlag); + args.append(mainexec); + app().setLauncherArgs(cliOptions.launcher, args); result = QGuiApplication::exec(); }