diff --git a/src/mumble/Overlay_win.cpp b/src/mumble/Overlay_win.cpp index 5693481f5..002891fc3 100644 --- a/src/mumble/Overlay_win.cpp +++ b/src/mumble/Overlay_win.cpp @@ -88,6 +88,10 @@ OverlayPrivateWin::OverlayPrivateWin(QObject *p) : OverlayPrivate(p) { connect(m_helper_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onHelperProcessExited(int, QProcess::ExitStatus))); + m_helper_restart_timer = new QTimer(this); + m_helper_restart_timer->setSingleShot(true); + connect(m_helper_restart_timer, SIGNAL(timeout()), this, SLOT(onDelayedRestartTimerTriggered())); + m_helper64_exe_path = QString::fromLatin1("%1/mumble_ol_x64.exe").arg(qApp->applicationDirPath()); m_helper64_exe_args = m_helper_exe_args; m_helper64_process = new QProcess(this); @@ -100,6 +104,10 @@ OverlayPrivateWin::OverlayPrivateWin(QObject *p) : OverlayPrivate(p) { connect(m_helper64_process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onHelperProcessExited(int, QProcess::ExitStatus))); + + m_helper64_restart_timer = new QTimer(this); + m_helper64_restart_timer->setSingleShot(true); + connect(m_helper64_restart_timer, SIGNAL(timeout()), this, SLOT(onDelayedRestartTimerTriggered())); } OverlayPrivateWin::~OverlayPrivateWin() { @@ -110,8 +118,10 @@ void OverlayPrivateWin::startHelper(QProcess *helper) { if (helper->state() == QProcess::NotRunning) { if (helper == m_helper_process) { helper->start(m_helper_exe_path, m_helper_exe_args); + m_helper_start_time.restart(); } else if (helper == m_helper64_process) { helper->start(m_helper64_exe_path, m_helper64_exe_args); + m_helper64_start_time.restart(); } } else { qWarning("OverlayPrivateWin: startHelper() called while process is already running. skipping."); @@ -194,11 +204,18 @@ void OverlayPrivateWin::onHelperProcessError(QProcess::ProcessError processError void OverlayPrivateWin::onHelperProcessExited(int exitCode, QProcess::ExitStatus exitStatus) { QProcess *helper = qobject_cast(sender()); + QString path; + qint64 elapsedMsec; + QTimer *restartTimer; if (helper == m_helper_process) { path = m_helper_exe_path; + elapsedMsec = m_helper_start_time.elapsed(); + restartTimer = m_helper_restart_timer; } else if (helper == m_helper64_process) { path = m_helper64_exe_path; + elapsedMsec = m_helper64_start_time.elapsed(); + restartTimer = m_helper64_restart_timer; } const char *helperErrString = OverlayHelperErrorToString(static_cast(exitCode)); @@ -210,7 +227,43 @@ void OverlayPrivateWin::onHelperProcessExited(int exitCode, QProcess::ExitStatus // If the helper process exited while we're in 'active' // mode, restart it. if (m_active) { + // If the helper was only recently started, be + // a little more patient with restarting it. + // We could be hitting a crash bug in the helper, + // and we don't want to do too much harm in that + // case by spawning thousands of processes. + qint64 cooldownMsec = (qint64) g.s.iOverlayWinHelperRestartCooldownMsec; + if (elapsedMsec < cooldownMsec) { + qint64 delayMsec = cooldownMsec - elapsedMsec; + qWarning("OverlayPrivateWin: waiting %llu seconds until restarting helper process '%s'. last restart was %llu seconds ago.", + (unsigned long long) delayMsec/1000ULL, + qPrintable(path), + (unsigned long long) elapsedMsec/1000ULL); + if (!restartTimer->isActive()) { + restartTimer->start(delayMsec); + } + } else { startHelper(helper); + } + } +} + +void OverlayPrivateWin::onDelayedRestartTimerTriggered() { + if (!m_active) { + return; + } + + QTimer *timer = qobject_cast(sender()); + + QProcess *helper = NULL; + if (timer == m_helper_restart_timer) { + helper = m_helper_process; + } else if (timer == m_helper64_restart_timer) { + helper = m_helper64_process; + } + + if (helper->state() == QProcess::NotRunning) { + startHelper(helper); } } diff --git a/src/mumble/Overlay_win.h b/src/mumble/Overlay_win.h index 334a6acb9..1041c2d2a 100644 --- a/src/mumble/Overlay_win.h +++ b/src/mumble/Overlay_win.h @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include "Overlay.h" @@ -52,15 +54,20 @@ class OverlayPrivateWin : public OverlayPrivate { void onHelperProcessStarted(); void onHelperProcessError(QProcess::ProcessError); void onHelperProcessExited(int exitCode, QProcess::ExitStatus exitStatus); + void onDelayedRestartTimerTriggered(); protected: QProcess *m_helper_process; QString m_helper_exe_path; QStringList m_helper_exe_args; + QElapsedTimer m_helper_start_time; + QTimer *m_helper_restart_timer; QProcess *m_helper64_process; QString m_helper64_exe_path; QStringList m_helper64_exe_args; + QElapsedTimer m_helper64_start_time; + QTimer *m_helper64_restart_timer; bool m_active; bool m_allow64bit; diff --git a/src/mumble/Settings.cpp b/src/mumble/Settings.cpp index 84255ff4b..845be36b5 100644 --- a/src/mumble/Settings.cpp +++ b/src/mumble/Settings.cpp @@ -345,6 +345,9 @@ Settings::Settings() { fAudioMaxDistVolume = 0.80f; fAudioBloom = 0.5f; + // OverlayPrivateWin + iOverlayWinHelperRestartCooldownMsec = 10000; + iLCDUserViewMinColWidth = 50; iLCDUserViewSplitterWidth = 2; @@ -696,7 +699,9 @@ void Settings::load(QSettings* settings_ptr) { SAVELOAD(bDisableCELT, "audio/disablecelt"); SAVELOAD(disablePublicList, "ui/disablepubliclist"); SAVELOAD(disableConnectDialogEditing, "ui/disableconnectdialogediting"); - + + // OverlayPrivateWin + SAVELOAD(iOverlayWinHelperRestartCooldownMsec, "overlay_win/helper/restart_cooldown_msec"); // LCD SAVELOAD(iLCDUserViewMinColWidth, "lcd/userview/mincolwidth"); @@ -990,6 +995,9 @@ void Settings::save() { SAVELOAD(disablePublicList, "ui/disablepubliclist"); SAVELOAD(disableConnectDialogEditing, "ui/disableconnectdialogediting"); + // OverlayPrivateWin + SAVELOAD(iOverlayWinHelperRestartCooldownMsec, "overlay_win/helper/restart_cooldown_msec"); + // LCD SAVELOAD(iLCDUserViewMinColWidth, "lcd/userview/mincolwidth"); SAVELOAD(iLCDUserViewSplitterWidth, "lcd/userview/splitterwidth"); diff --git a/src/mumble/Settings.h b/src/mumble/Settings.h index fd097dc2c..fda5a5c41 100644 --- a/src/mumble/Settings.h +++ b/src/mumble/Settings.h @@ -230,6 +230,8 @@ struct Settings { OverlaySettings os; + int iOverlayWinHelperRestartCooldownMsec; + int iLCDUserViewMinColWidth; int iLCDUserViewSplitterWidth; QMap qmLCDDevices;