Fix WebUI error handling

This commit is contained in:
Vladimir Golovnev (Glassez) 2017-11-05 15:56:13 +03:00 committed by sledgehammer999
parent ffa6f7ea34
commit 71bb6538db
No known key found for this signature in database
GPG key ID: 6E4A2D025B7CC9A2
4 changed files with 71 additions and 46 deletions

View file

@ -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<MainWindow> Application::mainWindow()
{
@ -483,7 +490,12 @@ int Application::exec(const QStringList &params)
#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) {

View file

@ -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<WebUI> m_webui;
WebUI *m_webui;
#endif
// FileLog

View file

@ -28,10 +28,6 @@
#include "webui.h"
#ifdef DISABLE_GUI
#include <QCoreApplication>
#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;
}

View file

@ -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<Http::Server> m_httpServer;
QPointer<Net::DNSUpdater> m_dnsUpdater;
QPointer<AbstractWebApplication> m_webapp;