diff --git a/src/app/application.cpp b/src/app/application.cpp index 86a5137cd..54747cda7 100644 --- a/src/app/application.cpp +++ b/src/app/application.cpp @@ -146,6 +146,13 @@ Application::Application(const QString &id, int &argc, char **argv) Logger::instance()->addMessage(tr("qBittorrent %1 started", "qBittorrent v3.2.0alpha started").arg(QBT_VERSION)); } +Application::~Application() +{ + // we still need to call cleanup() + // in case the App failed to start + cleanup(); +} + #ifndef DISABLE_GUI QPointer Application::mainWindow() { @@ -483,7 +490,12 @@ int Application::exec(const QStringList ¶ms) #ifndef DISABLE_WEBUI m_webui = new WebUI; -#endif +#ifdef DISABLE_GUI + if (m_webui->isErrored()) + return 1; + connect(m_webui, &WebUI::fatalError, this, []() { QCoreApplication::exit(1); }); +#endif // DISABLE_GUI +#endif // DISABLE_WEBUI new RSS::Session; // create RSS::Session singleton new RSS::AutoDownloader; // create RSS::AutoDownloader singleton @@ -642,37 +654,36 @@ void Application::shutdownCleanup(QSessionManager &manager) void Application::cleanup() { -#ifndef DISABLE_GUI -#ifdef Q_OS_WIN // cleanup() can be called multiple times during shutdown. We only need it once. static QAtomicInt alreadyDone; if (!alreadyDone.testAndSetAcquire(0, 1)) return; -#endif // Q_OS_WIN - // Hide the window and not leave it on screen as - // unresponsive. Also for Windows take the WinId - // after it's hidden, because hide() may cause a - // WinId change. - m_window->hide(); +#ifndef DISABLE_GUI + if (m_window) { + // Hide the window and not leave it on screen as + // unresponsive. Also for Windows take the WinId + // after it's hidden, because hide() may cause a + // WinId change. + m_window->hide(); #ifdef Q_OS_WIN - typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR); - PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)::GetProcAddress(::GetModuleHandleW(L"User32.dll"), "ShutdownBlockReasonCreate"); - // Only available on Vista+ - if (shutdownBRCreate) - shutdownBRCreate((HWND)m_window->effectiveWinId(), tr("Saving torrent progress...").toStdWString().c_str()); + typedef BOOL (WINAPI *PSHUTDOWNBRCREATE)(HWND, LPCWSTR); + PSHUTDOWNBRCREATE shutdownBRCreate = (PSHUTDOWNBRCREATE)::GetProcAddress(::GetModuleHandleW(L"User32.dll"), "ShutdownBlockReasonCreate"); + // Only available on Vista+ + if (shutdownBRCreate) + shutdownBRCreate((HWND)m_window->effectiveWinId(), tr("Saving torrent progress...").toStdWString().c_str()); #endif // Q_OS_WIN - // Do manual cleanup in MainWindow to force widgets - // to save their Preferences, stop all timers and - // delete as many widgets as possible to leave only - // a 'shell' MainWindow. - // We need a valid window handle for Windows Vista+ - // otherwise the system shutdown will continue even - // though we created a ShutdownBlockReason - m_window->cleanup(); - + // Do manual cleanup in MainWindow to force widgets + // to save their Preferences, stop all timers and + // delete as many widgets as possible to leave only + // a 'shell' MainWindow. + // We need a valid window handle for Windows Vista+ + // otherwise the system shutdown will continue even + // though we created a ShutdownBlockReason + m_window->cleanup(); + } #endif // DISABLE_GUI #ifndef DISABLE_WEBUI @@ -697,14 +708,16 @@ void Application::cleanup() Utils::Fs::removeDirRecursive(Utils::Fs::tempPath()); #ifndef DISABLE_GUI + if (m_window) { #ifdef Q_OS_WIN - typedef BOOL (WINAPI *PSHUTDOWNBRDESTROY)(HWND); - PSHUTDOWNBRDESTROY shutdownBRDestroy = (PSHUTDOWNBRDESTROY)::GetProcAddress(::GetModuleHandleW(L"User32.dll"), "ShutdownBlockReasonDestroy"); - // Only available on Vista+ - if (shutdownBRDestroy) - shutdownBRDestroy((HWND)m_window->effectiveWinId()); + typedef BOOL (WINAPI *PSHUTDOWNBRDESTROY)(HWND); + PSHUTDOWNBRDESTROY shutdownBRDestroy = (PSHUTDOWNBRDESTROY)::GetProcAddress(::GetModuleHandleW(L"User32.dll"), "ShutdownBlockReasonDestroy"); + // Only available on Vista+ + if (shutdownBRDestroy) + shutdownBRDestroy((HWND)m_window->effectiveWinId()); #endif // Q_OS_WIN - delete m_window; + delete m_window; + } #endif // DISABLE_GUI if (m_shutdownAct != ShutdownDialogAction::Exit) { diff --git a/src/app/application.h b/src/app/application.h index 67675e2e8..ae3bb63ef 100644 --- a/src/app/application.h +++ b/src/app/application.h @@ -73,9 +73,11 @@ namespace RSS class Application : public BaseApplication { Q_OBJECT + Q_DISABLE_COPY(Application) public: Application(const QString &id, int &argc, char **argv); + ~Application() override; #if (defined(Q_OS_WIN) && !defined(DISABLE_GUI)) bool isRunning(); @@ -132,7 +134,7 @@ private: #endif #ifndef DISABLE_WEBUI - QPointer m_webui; + WebUI *m_webui; #endif // FileLog diff --git a/src/webui/webui.cpp b/src/webui/webui.cpp index a0a906f3a..6b0e49629 100644 --- a/src/webui/webui.cpp +++ b/src/webui/webui.cpp @@ -28,10 +28,6 @@ #include "webui.h" -#ifdef DISABLE_GUI -#include -#endif - #include "base/http/server.h" #include "base/logger.h" #include "base/net/dnsupdater.h" @@ -39,18 +35,20 @@ #include "base/preferences.h" #include "webapplication.h" -WebUI::WebUI(QObject *parent) - : QObject(parent) +WebUI::WebUI() + : m_isErrored(false) , m_port(0) { - init(); - connect(Preferences::instance(), SIGNAL(changed()), SLOT(init())); + configure(); + connect(Preferences::instance(), &Preferences::changed, this, &WebUI::configure); } -void WebUI::init() +void WebUI::configure() { - Logger* const logger = Logger::instance(); - Preferences* const pref = Preferences::instance(); + m_isErrored = false; // clear previous error state + + Logger *const logger = Logger::instance(); + Preferences *const pref = Preferences::instance(); const quint16 oldPort = m_port; m_port = pref->getWebUiPort(); @@ -105,10 +103,10 @@ void WebUI::init() const QString errorMsg = tr("Web UI: Unable to bind to IP: %1, port: %2. Reason: %3") .arg(serverAddressString).arg(m_port).arg(m_httpServer->errorString()); logger->addMessage(errorMsg, Log::CRITICAL); -#ifdef DISABLE_GUI qCritical() << errorMsg; - QCoreApplication::exit(1); -#endif + + m_isErrored = true; + emit fatalError(); } } @@ -137,3 +135,8 @@ void WebUI::init() delete m_dnsUpdater; } } + +bool WebUI::isErrored() const +{ + return m_isErrored; +} diff --git a/src/webui/webui.h b/src/webui/webui.h index a7903640b..c552405e5 100644 --- a/src/webui/webui.h +++ b/src/webui/webui.h @@ -47,14 +47,21 @@ class AbstractWebApplication; class WebUI : public QObject { Q_OBJECT + Q_DISABLE_COPY(WebUI) public: - explicit WebUI(QObject *parent = 0); + WebUI(); + + bool isErrored() const; + +signals: + void fatalError(); private slots: - void init(); + void configure(); private: + bool m_isErrored; QPointer m_httpServer; QPointer m_dnsUpdater; QPointer m_webapp;