refactor: Improve Daemon uninstall exception flow
This commit is contained in:
parent
5a7f6bd1c0
commit
a6956b9516
2 changed files with 67 additions and 68 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Symless Ltd.
|
* SPDX-FileCopyrightText: (C) 2012 - 2016, 2025 Symless Ltd.
|
||||||
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
* SPDX-FileCopyrightText: (C) 2012 Nick Bolton
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
*/
|
*/
|
||||||
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
using namespace deskflow::core;
|
using namespace deskflow::core;
|
||||||
|
|
||||||
|
void handleError(const char *message);
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
|
|
@ -45,7 +47,16 @@ int main(int argc, char **argv)
|
||||||
LOG((CLOG_PRINT "%s daemon (v%s)", kAppName, kVersion));
|
LOG((CLOG_PRINT "%s daemon (v%s)", kAppName, kVersion));
|
||||||
|
|
||||||
auto &daemon = DaemonApp::instance();
|
auto &daemon = DaemonApp::instance();
|
||||||
const auto initResult = daemon.init(&events, argc, argv);
|
DaemonApp::InitResult initResult;
|
||||||
|
try {
|
||||||
|
initResult = daemon.init(&events, argc, argv);
|
||||||
|
} catch (std::exception &e) {
|
||||||
|
handleError(e.what());
|
||||||
|
return kExitFailed;
|
||||||
|
} catch (...) {
|
||||||
|
handleError("Unrecognized error.");
|
||||||
|
return kExitFailed;
|
||||||
|
}
|
||||||
|
|
||||||
switch (initResult) {
|
switch (initResult) {
|
||||||
using enum DaemonApp::InitResult;
|
using enum DaemonApp::InitResult;
|
||||||
|
|
@ -112,3 +123,14 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void handleError(const char *message)
|
||||||
|
{
|
||||||
|
// Always print error to stdout in case run as CLI program.
|
||||||
|
LOG_ERR("%s", message);
|
||||||
|
|
||||||
|
#if SYSAPI_WIN32
|
||||||
|
// Show a message box for when run from MSI in Win32 subsystem.
|
||||||
|
MessageBoxA(nullptr, message, "Deskflow daemon error", MB_OK | MB_ICONERROR);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -171,70 +171,58 @@ DaemonApp::InitResult DaemonApp::init(IEventQueue *events, int argc, char **argv
|
||||||
|
|
||||||
m_events = events;
|
m_events = events;
|
||||||
|
|
||||||
bool isUninstalling = false;
|
// default log level to system setting.
|
||||||
try {
|
if (string logLevel = ARCH->setting("LogLevel"); logLevel != "")
|
||||||
// default log level to system setting.
|
CLOG->setFilter(logLevel.c_str());
|
||||||
if (string logLevel = ARCH->setting("LogLevel"); logLevel != "")
|
|
||||||
CLOG->setFilter(logLevel.c_str());
|
|
||||||
|
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
string arg(argv[i]);
|
string arg(argv[i]);
|
||||||
|
|
||||||
if (arg == "-h" || arg == "--help") {
|
if (arg == "-h" || arg == "--help") {
|
||||||
showHelp(argc, argv);
|
showHelp(argc, argv);
|
||||||
return ShowHelp;
|
return ShowHelp;
|
||||||
} else if (arg == "-f" || arg == "--foreground") {
|
} else if (arg == "-f" || arg == "--foreground") {
|
||||||
m_foreground = true;
|
m_foreground = true;
|
||||||
}
|
}
|
||||||
#if SYSAPI_WIN32
|
#if SYSAPI_WIN32
|
||||||
else if (arg == "--install" || arg == "/install") {
|
else if (arg == "--install" || arg == "/install") {
|
||||||
LOG((CLOG_NOTE "installing windows daemon"));
|
LOG((CLOG_NOTE "installing windows daemon"));
|
||||||
ARCH->installDaemon();
|
ARCH->installDaemon();
|
||||||
return Installed;
|
return Installed;
|
||||||
} else if (arg == "--uninstall" || arg == "/uninstall") {
|
} else if (arg == "--uninstall" || arg == "/uninstall") {
|
||||||
LOG((CLOG_NOTE "uninstalling windows daemon"));
|
LOG((CLOG_NOTE "uninstalling windows daemon"));
|
||||||
isUninstalling = true;
|
try {
|
||||||
ARCH->uninstallDaemon();
|
ARCH->uninstallDaemon();
|
||||||
return Uninstalled;
|
} catch (XArch &e) {
|
||||||
|
std::string message = e.what();
|
||||||
|
if (message.find("The service has not been started") != std::string::npos) {
|
||||||
|
// HACK: this message happens intermittently, not sure where from but
|
||||||
|
// it's quite misleading for the user. they thing something has gone
|
||||||
|
// horribly wrong, but it's just the service manager reporting a false
|
||||||
|
// positive (the service has actually shut down in most cases).
|
||||||
|
LOG_DEBUG("ignoring service start error on uninstall: %s", message.c_str());
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return Uninstalled;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
else {
|
else {
|
||||||
stringstream ss;
|
LOG_ERR("unknown argument: %s", arg.c_str());
|
||||||
ss << "Unrecognized argument: " << arg;
|
return ArgsError;
|
||||||
handleError(ss.str().c_str());
|
|
||||||
showHelp(argc, argv);
|
|
||||||
return ArgsError;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_foreground) {
|
|
||||||
#if SYSAPI_WIN32
|
|
||||||
// Only use MS debug outputter when the process is daemonized, since stdout won't be accessible
|
|
||||||
// in that case, but is accessible when running in the foreground.
|
|
||||||
CLOG->insert(new MSWindowsDebugOutputter()); // NOSONAR - Adopted by `Log`
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return StartDaemon;
|
|
||||||
|
|
||||||
} catch (XArch &e) {
|
|
||||||
std::string message = e.what();
|
|
||||||
if (isUninstalling && (message.find("The service has not been started") != std::string::npos)) {
|
|
||||||
// TODO: if we're keeping this use error code instead (what is it?!).
|
|
||||||
// HACK: this message happens intermittently, not sure where from but
|
|
||||||
// it's quite misleading for the user. they thing something has gone
|
|
||||||
// horribly wrong, but it's just the service manager reporting a false
|
|
||||||
// positive (the service has actually shut down in most cases).
|
|
||||||
} else {
|
|
||||||
handleError(message.c_str());
|
|
||||||
}
|
|
||||||
} catch (std::exception &e) {
|
|
||||||
handleError(e.what());
|
|
||||||
} catch (...) {
|
|
||||||
handleError("Unrecognized error.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return FatalError;
|
if (!m_foreground) {
|
||||||
|
#if SYSAPI_WIN32
|
||||||
|
// Only use MS debug outputter when the process is daemonized, since stdout won't be accessible
|
||||||
|
// in that case, but is accessible when running in the foreground.
|
||||||
|
CLOG->insert(new MSWindowsDebugOutputter());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return StartDaemon;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DaemonApp::mainLoop(bool foreground)
|
void DaemonApp::mainLoop(bool foreground)
|
||||||
|
|
@ -280,17 +268,6 @@ void DaemonApp::mainLoop(bool foreground)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DaemonApp::handleError(const char *message)
|
|
||||||
{
|
|
||||||
// Always print error to stdout in case run as CLI program.
|
|
||||||
LOG_ERR("%s", message);
|
|
||||||
|
|
||||||
#if SYSAPI_WIN32
|
|
||||||
// Show a message box for when run from MSI in Win32 subsystem.
|
|
||||||
MessageBoxA(nullptr, message, "Deskflow daemon error", MB_OK | MB_ICONERROR);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string DaemonApp::logFilename()
|
std::string DaemonApp::logFilename()
|
||||||
{
|
{
|
||||||
string logFilename;
|
string logFilename;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue