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.
This commit is contained in:
Martchus 2021-06-21 23:18:51 +02:00
parent 04c82e3ec4
commit 0faacaa7c8
5 changed files with 27 additions and 12 deletions

View File

@ -1,5 +1,7 @@
#include "./syncthingprocess.h"
#include <syncthingconnector/syncthingconnection.h>
#include <QTimer>
#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();
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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();