From 0faacaa7c8c844d7211a9894d0069e19c268a345 Mon Sep 17 00:00:00 2001 From: Martchus Date: Mon, 21 Jun 2021 23:18:51 +0200 Subject: [PATCH] Terminate Syncthing gracefully via REST-API on non-UNIX platforms If there's a configured and local Syncthing connection and we're on a non-UNIX platform which doesn't support SIGTERM (basically Windows) it makes sense to use the REST-API instead. That's likely better than just terminating the process forcefully. This doesn't cover the stop button within the launcher settings yet because from this context is isn't clear which connection is relevant as there can be multiple tray icons/widgets but only one settings page. --- connector/syncthingprocess.cpp | 24 ++++++++++++++++++------ connector/syncthingprocess.h | 5 +++-- tray/gui/traywidget.cpp | 2 +- widgets/misc/syncthinglauncher.cpp | 4 ++-- widgets/misc/syncthinglauncher.h | 4 +++- 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/connector/syncthingprocess.cpp b/connector/syncthingprocess.cpp index 133b3d3..bf2a9d8 100644 --- a/connector/syncthingprocess.cpp +++ b/connector/syncthingprocess.cpp @@ -1,5 +1,7 @@ #include "./syncthingprocess.h" +#include + #include #ifdef LIB_SYNCTHING_CONNECTOR_BOOST_PROCESS @@ -185,9 +187,10 @@ QStringList SyncthingProcess::splitArguments(const QString &arguments) } /*! - * \brief Stops the currently running process. If it has been stopped, starts the specified \a program with the specified \a arguments. + * \brief Stops the currently running process gracefully. If it has been stopped, starts the specified \a program with the specified \a arguments. + * \sa See stopSyncthing() for details about \a currentConnection. */ -void SyncthingProcess::restartSyncthing(const QString &program, const QStringList &arguments) +void SyncthingProcess::restartSyncthing(const QString &program, const QStringList &arguments, SyncthingConnection *currentConnection) { if (!isRunning()) { startSyncthing(program, arguments); @@ -195,9 +198,7 @@ void SyncthingProcess::restartSyncthing(const QString &program, const QStringLis } m_program = program; m_arguments = arguments; - m_manuallyStopped = true; - m_killTimer.start(); - terminate(); + stopSyncthing(currentConnection); } /*! @@ -215,11 +216,22 @@ void SyncthingProcess::startSyncthing(const QString &program, const QStringList /*! * \brief Stops the currently running process gracefully. If it doesn't stop after 3 seconds, attempts to kill the process. + * \remarks + * If graceful stopping is not possible (under Windows) the process is attempted to be stopped via the REST-API using \a currentConnection. + * This is however only considered, if \a currentConnection is configured and a local connection. */ -void SyncthingProcess::stopSyncthing() +void SyncthingProcess::stopSyncthing(SyncthingConnection *currentConnection) { m_manuallyStopped = true; m_killTimer.start(); +#ifdef PLATFORM_UNIX + Q_UNUSED(currentConnection) +#else + if (currentConnection && !currentConnection->syncthingUrl().isEmpty() && !currentConnection->apiKey().isEmpty() && currentConnection->isLocal()) { + currentConnection->shutdown(); + return; + } +#endif terminate(); } diff --git a/connector/syncthingprocess.h b/connector/syncthingprocess.h index b2907c7..59bf579 100644 --- a/connector/syncthingprocess.h +++ b/connector/syncthingprocess.h @@ -15,6 +15,7 @@ namespace Data { +class SyncthingConnection; #ifdef LIB_SYNCTHING_CONNECTOR_BOOST_PROCESS struct SyncthingProcessInternalData; struct SyncthingProcessIOHandler; @@ -55,9 +56,9 @@ public: #endif public Q_SLOTS: - void restartSyncthing(const QString &program, const QStringList &arguments); + void restartSyncthing(const QString &program, const QStringList &arguments, SyncthingConnection *currentConnection = nullptr); void startSyncthing(const QString &program, const QStringList &arguments); - void stopSyncthing(); + void stopSyncthing(SyncthingConnection *currentConnection = nullptr); void killSyncthing(); #ifdef LIB_SYNCTHING_CONNECTOR_BOOST_PROCESS void terminate(); diff --git a/tray/gui/traywidget.cpp b/tray/gui/traywidget.cpp index 34111f4..ca3de93 100644 --- a/tray/gui/traywidget.cpp +++ b/tray/gui/traywidget.cpp @@ -682,7 +682,7 @@ void TrayWidget::toggleRunning() case StartStopButtonTarget::Launcher: if (auto *const launcher = SyncthingLauncher::mainInstance()) { if (launcher->isRunning()) { - launcher->terminate(); + launcher->terminate(&m_connection); } else { launcher->launch(Settings::values().launcher); } diff --git a/widgets/misc/syncthinglauncher.cpp b/widgets/misc/syncthinglauncher.cpp index 65d1caa..5d2dd4f 100644 --- a/widgets/misc/syncthinglauncher.cpp +++ b/widgets/misc/syncthinglauncher.cpp @@ -153,11 +153,11 @@ void SyncthingLauncher::launch(const LibSyncthing::RuntimeOptions &runtimeOption } #endif -void SyncthingLauncher::terminate() +void SyncthingLauncher::terminate(SyncthingConnection *relevantConnection) { if (m_process.isRunning()) { m_manuallyStopped = true; - m_process.stopSyncthing(); + m_process.stopSyncthing(relevantConnection); } else { tearDownLibSyncthing(); } diff --git a/widgets/misc/syncthinglauncher.h b/widgets/misc/syncthinglauncher.h index 6e915cb..f004a7d 100644 --- a/widgets/misc/syncthinglauncher.h +++ b/widgets/misc/syncthinglauncher.h @@ -18,6 +18,8 @@ struct Launcher; namespace Data { +class SyncthingConnection; + class SYNCTHINGWIDGETS_EXPORT SyncthingLauncher : public QObject { Q_OBJECT Q_PROPERTY(bool running READ isRunning NOTIFY runningChanged) @@ -57,7 +59,7 @@ Q_SIGNALS: public Q_SLOTS: void launch(const QString &program, const QStringList &arguments); void launch(const Settings::Launcher &launcherSettings); - void terminate(); + void terminate(SyncthingConnection *relevantConnection = nullptr); void kill(); void tearDownLibSyncthing();