feat(daemon): Friendly message on daemon connection error

This commit is contained in:
Nick Bolton 2025-04-15 21:52:36 +01:00 committed by Chris Rizzitello
parent c62b4ec068
commit 901dacf593
8 changed files with 86 additions and 28 deletions

View file

@ -289,6 +289,7 @@ void MainWindow::connectSlots()
connect(&m_coreProcess, &CoreProcess::processStateChanged, this, &MainWindow::coreProcessStateChanged); connect(&m_coreProcess, &CoreProcess::processStateChanged, this, &MainWindow::coreProcessStateChanged);
connect(&m_coreProcess, &CoreProcess::connectionStateChanged, this, &MainWindow::coreConnectionStateChanged); connect(&m_coreProcess, &CoreProcess::connectionStateChanged, this, &MainWindow::coreConnectionStateChanged);
connect(&m_coreProcess, &CoreProcess::secureSocket, this, &MainWindow::secureSocket); connect(&m_coreProcess, &CoreProcess::secureSocket, this, &MainWindow::secureSocket);
connect(&m_coreProcess, &CoreProcess::daemonIpcClientConnectFailed, this, &MainWindow::daemonIpcClientConnectFailed);
connect(m_actionAbout, &QAction::triggered, this, &MainWindow::openAboutDialog); connect(m_actionAbout, &QAction::triggered, this, &MainWindow::openAboutDialog);
connect(m_actionClearSettings, &QAction::triggered, this, &MainWindow::clearSettings); connect(m_actionClearSettings, &QAction::triggered, this, &MainWindow::clearSettings);
@ -365,6 +366,21 @@ void MainWindow::firstShown()
// hacky and fragile, so maybe there's a better approach. // hacky and fragile, so maybe there's a better approach.
const auto kCriticalDialogDelay = 100; const auto kCriticalDialogDelay = 100;
QTimer::singleShot(kCriticalDialogDelay, this, &messages::raiseCriticalDialog); QTimer::singleShot(kCriticalDialogDelay, this, &messages::raiseCriticalDialog);
if (!Settings::value(Settings::Gui::AutoUpdateCheck).isValid()) {
showAndActivate();
Settings::setValue(Settings::Gui::AutoUpdateCheck, messages::showUpdateCheckOption(this));
}
if (Settings::value(Settings::Gui::AutoUpdateCheck).toBool()) {
m_versionChecker.checkLatest();
} else {
qDebug() << "update check disabled";
}
if (Settings::value(Settings::Core::StartedBefore).toBool()) {
m_coreProcess.start();
}
} }
void MainWindow::settingsChanged(const QString &key) void MainWindow::settingsChanged(const QString &key)
@ -603,24 +619,6 @@ void MainWindow::serverConnectionConfigureClient(const QString &clientName)
void MainWindow::open() void MainWindow::open()
{ {
if (!Settings::value(Settings::Gui::AutoUpdateCheck).isValid()) {
showAndActivate();
Settings::setValue(Settings::Gui::AutoUpdateCheck, messages::showUpdateCheckOption(this));
}
if (Settings::value(Settings::Gui::AutoUpdateCheck).toBool()) {
m_versionChecker.checkLatest();
} else {
qDebug() << "update check disabled";
}
m_coreProcess.applyLogLevel();
if (Settings::value(Settings::Core::StartedBefore).toBool()) {
m_coreProcess.start();
}
Settings::value(Settings::Gui::Autohide).toBool() ? hide() : showAndActivate(); Settings::value(Settings::Gui::Autohide).toBool() ? hide() : showAndActivate();
} }
@ -1137,3 +1135,10 @@ bool MainWindow::regenerateLocalFingerprints()
updateLocalFingerprint(); updateLocalFingerprint();
return true; return true;
} }
void MainWindow::daemonIpcClientConnectFailed()
{
if (deskflow::gui::messages::showDaemonOffline(this)) {
m_coreProcess.retryDaemon();
}
}

View file

@ -158,6 +158,7 @@ private:
void showAndActivate(); void showAndActivate();
void showHostNameEditor(); void showHostNameEditor();
void setHostName(); void setHostName();
void daemonIpcClientConnectFailed();
/** /**
* @brief trustedFingerprintDb get the fingerprintDb for the trusted clients or trusted servers. * @brief trustedFingerprintDb get the fingerprintDb for the trusted clients or trusted servers.

View file

@ -309,4 +309,35 @@ bool showUpdateCheckOption(QWidget *parent)
return message.clickedButton() == checkButton; return message.clickedButton() == checkButton;
} }
bool showDaemonOffline(QWidget *parent)
{
QMessageBox message(parent);
message.setIcon(QMessageBox::Warning);
message.setWindowTitle(QObject::tr("Background service offline"));
message.addButton(QObject::tr("Retry"), QMessageBox::AcceptRole);
const auto ignore = message.addButton(QObject::tr("Ignore"), QMessageBox::RejectRole);
const auto disable = message.addButton(QObject::tr("Disable"), QMessageBox::NoRole);
message.setText(QString(
"<p>There was a problem finding the %1 background service (daemon).</p>"
"<p>The background service makes %1 work with UAC prompts and the login screen.</p>"
"<p>If don't want to use the background service and intentionally stopped it, "
"you can prevent it's use by disabling this feature.</p>"
"<p>If you did not stop the background service intentionally, there may be a problem with it. "
"Please retry or try restarting the %1 service from the Windows services program.</p>"
)
.arg(kAppName));
message.exec();
if (message.clickedButton() == ignore) {
return false;
} else if (message.clickedButton() == disable) {
Settings::setValue(Settings::Core::ProcessMode, Settings::ProcessMode::Desktop);
return false;
}
return true;
}
} // namespace deskflow::gui::messages } // namespace deskflow::gui::messages

View file

@ -49,4 +49,6 @@ void showWaylandLibraryError(QWidget *parent);
bool showUpdateCheckOption(QWidget *parent); bool showUpdateCheckOption(QWidget *parent);
bool showDaemonOffline(QWidget *parent);
} // namespace deskflow::gui::messages } // namespace deskflow::gui::messages

View file

@ -140,6 +140,7 @@ CoreProcess::CoreProcess(const IServerConfig &serverConfig, std::shared_ptr<Deps
m_daemonIpcClient{new ipc::DaemonIpcClient(this)} m_daemonIpcClient{new ipc::DaemonIpcClient(this)}
{ {
connect(m_daemonIpcClient, &ipc::DaemonIpcClient::connected, this, &CoreProcess::daemonIpcClientConnected); connect(m_daemonIpcClient, &ipc::DaemonIpcClient::connected, this, &CoreProcess::daemonIpcClientConnected);
connect(m_daemonIpcClient, &ipc::DaemonIpcClient::connectFailed, this, &CoreProcess::daemonIpcClientConnectFailed);
connect(&m_pDeps->process(), &QProcessProxy::finished, this, &CoreProcess::onProcessFinished); connect(&m_pDeps->process(), &QProcessProxy::finished, this, &CoreProcess::onProcessFinished);
@ -224,7 +225,7 @@ void CoreProcess::applyLogLevel()
if (processMode == ProcessMode::Service) { if (processMode == ProcessMode::Service) {
qDebug() << "setting daemon log level:" << Settings::logLevelText(); qDebug() << "setting daemon log level:" << Settings::logLevelText();
if (!m_daemonIpcClient->sendLogLevel(Settings::logLevelText())) { if (!m_daemonIpcClient->sendLogLevel(Settings::logLevelText())) {
qCritical() << "failed to set daemon ipc log level"; qWarning() << "failed to set daemon ipc log level";
} }
} }
} }
@ -263,7 +264,7 @@ void CoreProcess::startProcessFromDaemon(const QString &app, const QStringList &
qInfo("running command: %s", qPrintable(commandQuoted)); qInfo("running command: %s", qPrintable(commandQuoted));
if (!m_daemonIpcClient->sendStartProcess(commandQuoted, Settings::value(Settings::Daemon::Elevate).toBool())) { if (!m_daemonIpcClient->sendStartProcess(commandQuoted, Settings::value(Settings::Daemon::Elevate).toBool())) {
qCritical("cannot start process, ipc command failed"); qWarning("cannot start process, ipc command failed");
return; return;
} }
@ -297,7 +298,7 @@ void CoreProcess::stopProcessFromDaemon()
} }
if (!m_daemonIpcClient->sendStopProcess()) { if (!m_daemonIpcClient->sendStopProcess()) {
qCritical("cannot stop process, ipc command failed"); qWarning("cannot stop process, ipc command failed");
return; return;
} }
@ -736,4 +737,11 @@ void CoreProcess::clearSettings()
m_daemonIpcClient->sendClearSettings(); m_daemonIpcClient->sendClearSettings();
} }
void CoreProcess::retryDaemon()
{
if (m_daemonIpcClient->connectToServer()) {
qInfo("successfully reconnected to daemon");
}
}
} // namespace deskflow::gui } // namespace deskflow::gui

View file

@ -79,6 +79,7 @@ public:
void cleanup(); void cleanup();
void applyLogLevel(); void applyLogLevel();
void clearSettings(); void clearSettings();
void retryDaemon();
// getters // getters
Settings::CoreMode mode() const Settings::CoreMode mode() const
@ -119,6 +120,7 @@ signals:
void connectionStateChanged(ConnectionState state); void connectionStateChanged(ConnectionState state);
void processStateChanged(ProcessState state); void processStateChanged(ProcessState state);
void secureSocket(bool enabled); void secureSocket(bool enabled);
void daemonIpcClientConnectFailed();
private slots: private slots:
void onProcessFinished(int exitCode, QProcess::ExitStatus); void onProcessFinished(int exitCode, QProcess::ExitStatus);

View file

@ -27,20 +27,32 @@ DaemonIpcClient::DaemonIpcClient(QObject *parent)
bool DaemonIpcClient::connectToServer() bool DaemonIpcClient::connectToServer()
{ {
qDebug() << "daemon ipc client connecting to server:" << kDaemonIpcName; if (m_connecting) {
qDebug() << "daemon ipc client already connecting to server";
return false;
}
qDebug() << "daemon ipc client connecting to server:" << kDaemonIpcName;
m_connecting = true;
m_socket->connectToServer(kDaemonIpcName); m_socket->connectToServer(kDaemonIpcName);
if (!m_socket->waitForConnected(kTimeout)) { if (!m_socket->waitForConnected(kTimeout)) {
qWarning() << "daemon ipc client failed to connect"; qWarning() << "daemon ipc client failed to connect";
m_connecting = false;
Q_EMIT connectFailed();
return false; return false;
} }
if (!sendMessage("hello", "hello", false)) { if (!sendMessage("hello", "hello", false)) {
qWarning() << "daemon ipc client failed to send hello"; qWarning() << "daemon ipc client failed to send hello";
m_connecting = false;
Q_EMIT connectFailed();
return false; return false;
} }
m_connecting = false;
m_connected = true; m_connected = true;
qDebug() << "daemon ipc client connected"; qDebug() << "daemon ipc client connected";
Q_EMIT connected(); Q_EMIT connected();
@ -51,10 +63,7 @@ void DaemonIpcClient::handleDisconnected()
{ {
qWarning() << "daemon ipc client disconnected from server"; qWarning() << "daemon ipc client disconnected from server";
m_connected = false; m_connected = false;
Q_EMIT connectFailed();
if (!connectToServer()) {
qWarning() << "daemon ipc client failed to reconnect to server";
}
} }
void DaemonIpcClient::handleErrorOccurred() void DaemonIpcClient::handleErrorOccurred()

View file

@ -8,8 +8,6 @@
#include <QObject> #include <QObject>
#include "common/Settings.h"
class QLocalSocket; class QLocalSocket;
namespace deskflow::gui::ipc { namespace deskflow::gui::ipc {
@ -34,6 +32,7 @@ public:
signals: signals:
void connected(); void connected();
void connectFailed();
private slots: private slots:
void handleDisconnected(); void handleDisconnected();
@ -46,6 +45,7 @@ private:
private: private:
QLocalSocket *m_socket; QLocalSocket *m_socket;
bool m_connected{false}; bool m_connected{false};
bool m_connecting{false};
}; };
} // namespace deskflow::gui::ipc } // namespace deskflow::gui::ipc