Fix re-connect when process status is considered and Syncthing restarted

When Syncthing restarts itself, its main process is not terminating (as its
main process is just a monitoring process). The "Consider process status …"
feature was relying on the process being stopped and started again as
trigger for trying to re-connect, though. To make it also work when
Syncthing restarts itself, this change checks the log for an exiting
message of the monitoring process and considers the process running again
when the GUI address is logged again.

This fixes https://github.com/Martchus/syncthingtray/issues/236.

Notifications are not (yet) suppressed. (Not sure how easy it is and how
much sense it makes.)
This commit is contained in:
Martchus 2024-06-20 01:22:45 +02:00
parent ce92ccf677
commit 8f78d14215
5 changed files with 34 additions and 3 deletions

View File

@ -45,6 +45,8 @@ SyncthingLauncher::SyncthingLauncher(QObject *parent)
, m_relevantConnection(nullptr) , m_relevantConnection(nullptr)
, m_guiListeningUrlSearch("Access the GUI via the following URL: ", "\n\r", std::string_view(), , m_guiListeningUrlSearch("Access the GUI via the following URL: ", "\n\r", std::string_view(),
std::bind(&SyncthingLauncher::handleGuiListeningUrlFound, this, std::placeholders::_1, std::placeholders::_2)) std::bind(&SyncthingLauncher::handleGuiListeningUrlFound, this, std::placeholders::_1, std::placeholders::_2))
, m_exitSearch("Syncthing exited: ", "\n\r", std::string_view(),
std::bind(&SyncthingLauncher::handleExitFound, this, std::placeholders::_1, std::placeholders::_2))
#ifdef SYNCTHINGWIDGETS_USE_LIBSYNCTHING #ifdef SYNCTHINGWIDGETS_USE_LIBSYNCTHING
, m_libsyncthingLogLevel(LibSyncthing::LogLevel::Info) , m_libsyncthingLogLevel(LibSyncthing::LogLevel::Info)
#endif #endif
@ -332,6 +334,7 @@ void SyncthingLauncher::handleLoggingCallback(LibSyncthing::LogLevel level, cons
void SyncthingLauncher::handleOutputAvailable(QByteArray &&data) void SyncthingLauncher::handleOutputAvailable(QByteArray &&data)
{ {
m_guiListeningUrlSearch(data.data(), static_cast<std::size_t>(data.size())); m_guiListeningUrlSearch(data.data(), static_cast<std::size_t>(data.size()));
m_exitSearch(data.data(), static_cast<std::size_t>(data.size()));
if (isEmittingOutput()) { if (isEmittingOutput()) {
emit outputAvailable(data); emit outputAvailable(data);
} else { } else {
@ -339,12 +342,23 @@ void SyncthingLauncher::handleOutputAvailable(QByteArray &&data)
} }
} }
void SyncthingLauncher::handleGuiListeningUrlFound(CppUtilities::BufferSearch &, std::string &&searchResult) void SyncthingLauncher::handleGuiListeningUrlFound(CppUtilities::BufferSearch &search, std::string &&searchResult)
{ {
m_guiListeningUrl.setUrl(QString::fromStdString(searchResult)); m_guiListeningUrl.setUrl(QString::fromStdString(searchResult));
std::cerr << EscapeCodes::Phrases::Info << "Syncthing GUI available: " << searchResult << EscapeCodes::Phrases::End;
search.reset();
emit guiUrlChanged(m_guiListeningUrl); emit guiUrlChanged(m_guiListeningUrl);
} }
void SyncthingLauncher::handleExitFound(CppUtilities::BufferSearch &search, std::string &&searchResult)
{
m_guiListeningUrl.clear();
std::cerr << EscapeCodes::Phrases::Info << "Syncthing exited: " << searchResult << EscapeCodes::Phrases::End;
emit guiUrlChanged(m_guiListeningUrl);
emit exitLogged(std::move(searchResult));
search.reset();
}
void SyncthingLauncher::terminateDueToMeteredConnection() void SyncthingLauncher::terminateDueToMeteredConnection()
{ {
if (!isRunning()) { if (!isRunning()) {
@ -366,6 +380,8 @@ void SyncthingLauncher::runLibSyncthing(const LibSyncthing::RuntimeOptions &runt
LibSyncthing::setLoggingCallback(bind(&SyncthingLauncher::handleLoggingCallback, this, _1, _2, _3)); LibSyncthing::setLoggingCallback(bind(&SyncthingLauncher::handleLoggingCallback, this, _1, _2, _3));
emit runningChanged(true); emit runningChanged(true);
const auto exitCode = LibSyncthing::runSyncthing(runtimeOptions); const auto exitCode = LibSyncthing::runSyncthing(runtimeOptions);
m_guiListeningUrl.clear();
emit guiUrlChanged(m_guiListeningUrl);
emit exited(static_cast<int>(exitCode), exitCode == 0 ? QProcess::NormalExit : QProcess::CrashExit); emit exited(static_cast<int>(exitCode), exitCode == 0 ? QProcess::NormalExit : QProcess::CrashExit);
emit runningChanged(false); emit runningChanged(false);
} }

View File

@ -70,6 +70,7 @@ Q_SIGNALS:
void confirmKill(); void confirmKill();
void runningChanged(bool isRunning); void runningChanged(bool isRunning);
void outputAvailable(const QByteArray &data); void outputAvailable(const QByteArray &data);
void exitLogged(const std::string &exitMessage);
void exited(int exitCode, QProcess::ExitStatus exitStatus); void exited(int exitCode, QProcess::ExitStatus exitStatus);
void errorOccurred(QProcess::ProcessError error); void errorOccurred(QProcess::ProcessError error);
void guiUrlChanged(const QUrl &newUrl); void guiUrlChanged(const QUrl &newUrl);
@ -99,7 +100,8 @@ private:
void handleLoggingCallback(LibSyncthing::LogLevel, const char *message, std::size_t messageSize); void handleLoggingCallback(LibSyncthing::LogLevel, const char *message, std::size_t messageSize);
#endif #endif
void handleOutputAvailable(QByteArray &&data); void handleOutputAvailable(QByteArray &&data);
void handleGuiListeningUrlFound(CppUtilities::BufferSearch &bufferSearch, std::string &&searchResult); void handleGuiListeningUrlFound(CppUtilities::BufferSearch &search, std::string &&searchResult);
void handleExitFound(CppUtilities::BufferSearch &search, std::string &&searchResult);
void terminateDueToMeteredConnection(); void terminateDueToMeteredConnection();
SyncthingProcess m_process; SyncthingProcess m_process;
@ -110,6 +112,7 @@ private:
QFuture<void> m_stopFuture; QFuture<void> m_stopFuture;
QByteArray m_outputBuffer; QByteArray m_outputBuffer;
CppUtilities::BufferSearch m_guiListeningUrlSearch; CppUtilities::BufferSearch m_guiListeningUrlSearch;
CppUtilities::BufferSearch m_exitSearch;
CppUtilities::DateTime m_futureStarted; CppUtilities::DateTime m_futureStarted;
#ifdef SYNCTHINGWIDGETS_USE_LIBSYNCTHING #ifdef SYNCTHINGWIDGETS_USE_LIBSYNCTHING
LibSyncthing::LogLevel m_libsyncthingLogLevel; LibSyncthing::LogLevel m_libsyncthingLogLevel;

View File

@ -238,7 +238,7 @@ Launcher::LauncherStatus Launcher::apply(
return LauncherStatus{}; return LauncherStatus{};
} }
const auto isRelevant = connection.isLocal(); const auto isRelevant = connection.isLocal();
const auto isRunning = launcher->isRunning(); const auto isRunning = launcher->isRunning() && !launcher->guiUrl().isEmpty();
const auto consideredForReconnect = considerForReconnect && isRelevant; const auto consideredForReconnect = considerForReconnect && isRelevant;
connectAccordingToSettings( connectAccordingToSettings(
connection, currentConnectionSettings, *launcher, reconnectRequired, considerForReconnect, isRelevant, isRunning, consideredForReconnect); connection, currentConnectionSettings, *launcher, reconnectRequired, considerForReconnect, isRelevant, isRunning, consideredForReconnect);

View File

@ -222,6 +222,7 @@ TrayWidget::TrayWidget(TrayMenu *parent)
connect(m_ui->startStopPushButton, &QPushButton::clicked, this, &TrayWidget::toggleRunning); connect(m_ui->startStopPushButton, &QPushButton::clicked, this, &TrayWidget::toggleRunning);
if (const auto *const launcher = SyncthingLauncher::mainInstance()) { if (const auto *const launcher = SyncthingLauncher::mainInstance()) {
connect(launcher, &SyncthingLauncher::runningChanged, this, &TrayWidget::handleLauncherStatusChanged); connect(launcher, &SyncthingLauncher::runningChanged, this, &TrayWidget::handleLauncherStatusChanged);
connect(launcher, &SyncthingLauncher::guiUrlChanged, this, &TrayWidget::handleLauncherGuiAddressChanged);
} }
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD #ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
if (const auto *const service = SyncthingService::mainInstance()) { if (const auto *const service = SyncthingService::mainInstance()) {
@ -847,6 +848,16 @@ Settings::Launcher::LauncherStatus TrayWidget::handleLauncherStatusChanged()
return launcherStatus; return launcherStatus;
} }
Settings::Launcher::LauncherStatus TrayWidget::handleLauncherGuiAddressChanged(const QUrl &guiAddress)
{
Q_UNUSED(guiAddress)
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD
return applyLauncherSettings(false, Settings::values().systemd.considerForReconnect, true);
#else
return applyLauncherSettings(false);
#endif
}
Settings::Launcher::LauncherStatus TrayWidget::applyLauncherSettings(bool reconnectRequired, bool skipApplyingToConnection, bool skipStartStopButton) Settings::Launcher::LauncherStatus TrayWidget::applyLauncherSettings(bool reconnectRequired, bool skipApplyingToConnection, bool skipStartStopButton)
{ {
// update connection // update connection

View File

@ -105,6 +105,7 @@ private Q_SLOTS:
void updateIconAndTooltip(); void updateIconAndTooltip();
void toggleRunning(); void toggleRunning();
Settings::Launcher::LauncherStatus handleLauncherStatusChanged(); Settings::Launcher::LauncherStatus handleLauncherStatusChanged();
Settings::Launcher::LauncherStatus handleLauncherGuiAddressChanged(const QUrl &guiAddress);
Settings::Launcher::LauncherStatus applyLauncherSettings( Settings::Launcher::LauncherStatus applyLauncherSettings(
bool reconnectRequired = false, bool skipApplyingToConnection = false, bool skipStartStopButton = false); bool reconnectRequired = false, bool skipApplyingToConnection = false, bool skipStartStopButton = false);
#ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD #ifdef LIB_SYNCTHING_CONNECTOR_SUPPORT_SYSTEMD