From 6f7f418ec1ac9dc7b279b84cec0b0fb6ee80a1f3 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Tue, 21 Nov 2023 14:05:32 +0800 Subject: [PATCH] Improve error message when daemonizing failed PR #19959. --- src/app/application.cpp | 5 +++-- src/app/application.h | 2 +- src/app/main.cpp | 30 +++++++++++++++++++----------- src/base/utils/os.cpp | 10 +++------- 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/app/application.cpp b/src/app/application.cpp index af8d92b63..df8891e5a 100644 --- a/src/app/application.cpp +++ b/src/app/application.cpp @@ -292,7 +292,8 @@ Application::Application(int &argc, char **argv) connect(this, &QGuiApplication::commitDataRequest, this, &Application::shutdownCleanup, Qt::DirectConnection); #endif - LogMsg(tr("qBittorrent %1 started", "qBittorrent v3.2.0alpha started").arg(QStringLiteral(QBT_VERSION))); + LogMsg(tr("qBittorrent %1 started. Process ID: %2", "qBittorrent v3.2.0alpha started") + .arg(QStringLiteral(QBT_VERSION), QString::number(QCoreApplication::applicationPid()))); if (portableModeEnabled) { LogMsg(tr("Running in portable mode. Auto detected profile folder at: %1").arg(profileDir.toString())); @@ -944,7 +945,7 @@ int Application::exec() return BaseApplication::exec(); } -bool Application::isRunning() +bool Application::hasAnotherInstance() const { return !m_instanceManager->isFirstInstance(); } diff --git a/src/app/application.h b/src/app/application.h index ff7c4ace4..678325949 100644 --- a/src/app/application.h +++ b/src/app/application.h @@ -101,7 +101,7 @@ public: int exec(); - bool isRunning(); + bool hasAnotherInstance() const; bool callMainInstance(); const QBtCommandLineParameters &commandLineArgs() const; diff --git a/src/app/main.cpp b/src/app/main.cpp index 6cb174c6c..18623146e 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -73,6 +73,7 @@ Q_IMPORT_PLUGIN(QICOPlugin) #endif // DISABLE_GUI #include "base/global.h" +#include "base/logger.h" #include "base/preferences.h" #include "base/profile.h" #include "base/version.h" @@ -125,7 +126,7 @@ int main(int argc, char *argv[]) #ifdef Q_OS_WIN // QCoreApplication::applicationDirPath() needs an Application object instantiated first // Let's hope that there won't be a crash before this line - const char *envName = "_NT_SYMBOL_PATH"; + const char envName[] = "_NT_SYMBOL_PATH"; const QString envValue = qEnvironmentVariable(envName); if (envValue.isEmpty()) qputenv(envName, Application::applicationDirPath().toLocal8Bit()); @@ -185,13 +186,13 @@ int main(int argc, char *argv[]) setCurrentMigrationVersion(); } - // Check if qBittorrent is already running for this user - if (app->isRunning()) + // Check if qBittorrent is already running + if (app->hasAnotherInstance()) { #if defined(DISABLE_GUI) && !defined(Q_OS_WIN) if (params.shouldDaemonize) { - throw CommandLineParameterError(QCoreApplication::translate("Main", "You cannot use %1: qBittorrent is already running for this user.") + throw CommandLineParameterError(QCoreApplication::translate("Main", "You cannot use %1: qBittorrent is already running.") .arg(u"-d (or --daemon)"_s)); } #endif @@ -221,8 +222,7 @@ int main(int argc, char *argv[]) // Since Apple made difficult for users to set PATH, we set here for convenience. // Users are supposed to install Homebrew Python for search function. // For more info see issue #5571. - QByteArray path = "/usr/local/bin:"; - path += qgetenv("PATH"); + const QByteArray path = "/usr/local/bin:" + qgetenv("PATH"); qputenv("PATH", path.constData()); // On OS X the standard is to not show icons in the menus @@ -235,19 +235,27 @@ int main(int argc, char *argv[]) #if defined(DISABLE_GUI) && !defined(Q_OS_WIN) if (params.shouldDaemonize) { - app.reset(); // Destroy current application - if (daemon(1, 0) == 0) + app.reset(); // Destroy current application instance + if (::daemon(1, 0) == 0) { app = std::make_unique(argc, argv); - if (app->isRunning()) + if (app->hasAnotherInstance()) { - // Another instance had time to start. + // It is undefined behavior to write to log file since there is another qbt instance + // in play. But we still do it since there is chance that the log message will survive. + const QString errorMessage = QCoreApplication::translate("Main", "Found unexpected qBittorrent instance. Exiting this instance. Current process ID: %1.") + .arg(QString::number(QCoreApplication::applicationPid())); + LogMsg(errorMessage, Log::CRITICAL); + // stdout, stderr is closed so we can't use them return EXIT_FAILURE; } } else { - qCritical("Something went wrong while daemonizing, exiting..."); + const QString errorMessage = QCoreApplication::translate("Main", "Error when daemonizing. Reason: \"%1\". Error code: %2.") + .arg(QString::fromLocal8Bit(strerror(errno)), QString::number(errno)); + LogMsg(errorMessage, Log::CRITICAL); + qCritical("%s", qUtf8Printable(errorMessage)); return EXIT_FAILURE; } } diff --git a/src/base/utils/os.cpp b/src/base/utils/os.cpp index 0430652be..8bfd7d07e 100644 --- a/src/base/utils/os.cpp +++ b/src/base/utils/os.cpp @@ -31,8 +31,6 @@ #include "os.h" #ifdef Q_OS_WIN -#include - #include #include #include @@ -87,11 +85,9 @@ void Utils::OS::shutdownComputer([[maybe_unused]] const ShutdownDialogAction &ac } else { - const QString msg = QCoreApplication::translate("misc" - , "qBittorrent will shutdown the computer now because all downloads are complete."); - auto msgWchar = std::make_unique(msg.length() + 1); - msg.toWCharArray(msgWchar.get()); - ::InitiateSystemShutdownW(nullptr, msgWchar.get(), 10, TRUE, FALSE); + std::wstring msg = QCoreApplication::translate("misc" + , "qBittorrent will shutdown the computer now because all downloads are complete.").toStdWString(); + ::InitiateSystemShutdownW(nullptr, msg.data(), 10, TRUE, FALSE); } // Disable shutdown privilege.