From b067c043093eb1e80ffd17daf88975d6ac59d1fc Mon Sep 17 00:00:00 2001 From: Enrico Forestieri Date: Wed, 7 Mar 2012 00:26:17 +0000 Subject: [PATCH] Fix bug #8032 (timeout when using the Sweave module) After the timeout elapses, the user is notified that a command is taking a long time to complete and is given the choice to stop it. If the user decides to let the command run, the timeout is increased, otherwise the command is killed. One is prompted a first time after 3 mins, a second time after 9 mins, a third time after 27 mins, and so on, i.e., the n-th prompt occurs after 3^n minutes. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_2_0_X@40881 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/frontends/qt4/GuiProgress.cpp | 10 ++++++ src/frontends/qt4/GuiProgress.h | 4 +++ src/support/ProgressInterface.h | 5 +++ src/support/Systemcall.cpp | 53 ++++++++++++++++++++++++++++--- src/support/os.cpp | 6 ++++ src/support/os_cygwin.cpp | 6 ---- src/support/os_unix.cpp | 6 ---- src/support/os_win32.cpp | 6 ---- status.20x | 3 ++ 9 files changed, 77 insertions(+), 22 deletions(-) diff --git a/src/frontends/qt4/GuiProgress.cpp b/src/frontends/qt4/GuiProgress.cpp index aec058cf8e..ab8c6bd3cf 100644 --- a/src/frontends/qt4/GuiProgress.cpp +++ b/src/frontends/qt4/GuiProgress.cpp @@ -17,6 +17,8 @@ #include "qt_helpers.h" +#include "frontends/alert.h" + #include "support/debug.h" #include "support/Systemcall.h" @@ -67,6 +69,14 @@ GuiProgress::GuiProgress() } +int GuiProgress::prompt(docstring const & title, docstring const & question, + int default_button, int cancel_button, + docstring const & b1, docstring const & b2) +{ + return Alert::prompt(title, question, default_button, cancel_button, b1, b2); +} + + QString GuiProgress::currentTime() { return QTime::currentTime().toString("hh:mm:ss.zzz"); diff --git a/src/frontends/qt4/GuiProgress.h b/src/frontends/qt4/GuiProgress.h index 1d80259f71..a514733eb7 100644 --- a/src/frontends/qt4/GuiProgress.h +++ b/src/frontends/qt4/GuiProgress.h @@ -42,6 +42,10 @@ public: void lyxerrDisconnect(); void lyxerrFlush(); + int prompt(docstring const & title, docstring const & question, + int default_button, int cancel_button, + docstring const & b1, docstring const & b2); + static QString currentTime(); Q_SIGNALS: diff --git a/src/support/ProgressInterface.h b/src/support/ProgressInterface.h index a9b6d2bc43..1efb79a7e3 100644 --- a/src/support/ProgressInterface.h +++ b/src/support/ProgressInterface.h @@ -12,6 +12,8 @@ #ifndef LYX_SUPPORT_PROGRESSINTERFACE_H #define LYX_SUPPORT_PROGRESSINTERFACE_H +#include "support/strfwd.h" + class QString; namespace lyx { @@ -36,6 +38,9 @@ public: virtual void toggleWarning(QString const & title, QString const & msg, QString const & formatted) = 0; virtual void error(QString const & title, QString const & message) = 0; virtual void information(QString const & title, QString const & message) = 0; + virtual int prompt(docstring const & title, docstring const & question, + int default_button, int cancel_button, + docstring const & b1, docstring const & b2) = 0; virtual void lyxerrConnect() = 0; virtual void lyxerrDisconnect() = 0; diff --git a/src/support/Systemcall.cpp b/src/support/Systemcall.cpp index 100023e29d..7d22d592da 100644 --- a/src/support/Systemcall.cpp +++ b/src/support/Systemcall.cpp @@ -15,6 +15,7 @@ #include "support/debug.h" #include "support/filetools.h" +#include "support/gettext.h" #include "support/lstrings.h" #include "support/qstring_helpers.h" #include "support/Systemcall.h" @@ -72,6 +73,8 @@ public: void toggleWarning(QString const &, QString const &, QString const &) {} void error(QString const &, QString const &) {} void information(QString const &, QString const &) {} + int prompt(docstring const &, docstring const &, int default_but, int, + docstring const &, docstring const &) { return default_but; } }; @@ -363,11 +366,26 @@ void SystemcallPrivate::waitAndProcessEvents() } +namespace { + +bool queryStopCommand(QString const & cmd) +{ + docstring text = bformat(_( + "The command\n%1$s\nhas not yet completed.\n\n" + "Do you want to stop it?"), qstring_to_ucs4(cmd)); + return ProgressInterface::instance()->prompt(_("Stop command?"), text, + 1, 1, _("&Stop it"), _("Let it &run")) == 0; +} + +} + + bool SystemcallPrivate::waitWhile(State waitwhile, bool process_events, int timeout) { if (!process_) return false; + bool timedout = false; process_events_ = process_events; // Block GUI while waiting, @@ -375,8 +393,24 @@ bool SystemcallPrivate::waitWhile(State waitwhile, bool process_events, int time if (!process_events_) { if (waitwhile == Starting) return process_->waitForStarted(timeout); - if (waitwhile == Running) - return process_->waitForFinished(timeout); + if (waitwhile == Running) { + int bump = 2; + while (!timedout) { + if (process_->waitForFinished(timeout)) + return true; + bool stop = queryStopCommand(cmd_); + // The command may have finished in the meantime + if (process_->state() == QProcess::NotRunning) + return true; + if (stop) { + timedout = true; + process_->kill(); + } else { + timeout *= bump; + bump = 3; + } + } + } return false; } @@ -391,10 +425,21 @@ bool SystemcallPrivate::waitWhile(State waitwhile, bool process_events, int time // process events while waiting whith timeout QTime timer; timer.start(); - while (state == waitwhile && state != Error && timer.elapsed() < timeout) { + while (state == waitwhile && state != Error && !timedout) { waitAndProcessEvents(); + if (timer.elapsed() > timeout) { + bool stop = queryStopCommand(cmd_); + // The command may have finished in the meantime + if (process_->state() == QProcess::NotRunning) + break; + if (stop) { + timedout = true; + process_->kill(); + } else + timeout *= 3; + } } - return (state != Error) && (timer.elapsed() < timeout); + return (state != Error) && !timedout; } diff --git a/src/support/os.cpp b/src/support/os.cpp index f36331cccc..38c6374768 100644 --- a/src/support/os.cpp +++ b/src/support/os.cpp @@ -54,6 +54,12 @@ static string const python2(string const & binary, bool verbose = false) } +int timeout_min() +{ + return 30; +} + + string const python() { // Check whether the first python in PATH is the right one. diff --git a/src/support/os_cygwin.cpp b/src/support/os_cygwin.cpp index 389b4e2f78..b1c2fefd88 100644 --- a/src/support/os_cygwin.cpp +++ b/src/support/os_cygwin.cpp @@ -398,12 +398,6 @@ shell_type shell() } -int timeout_min() -{ - return 3; -} - - char path_separator(path_type type) { if (type == TEXENGINE) diff --git a/src/support/os_unix.cpp b/src/support/os_unix.cpp index b8a94b2c56..bb6a86b709 100644 --- a/src/support/os_unix.cpp +++ b/src/support/os_unix.cpp @@ -222,12 +222,6 @@ shell_type shell() } -int timeout_min() -{ - return 3; -} - - char path_separator(path_type) { return ':'; diff --git a/src/support/os_win32.cpp b/src/support/os_win32.cpp index 72bf218a04..b58397d202 100644 --- a/src/support/os_win32.cpp +++ b/src/support/os_win32.cpp @@ -458,12 +458,6 @@ shell_type shell() } -int timeout_min() -{ - return 30; -} - - char path_separator(path_type type) { if (type == TEXENGINE) diff --git a/status.20x b/status.20x index 3372b7c149..53629b7635 100644 --- a/status.20x +++ b/status.20x @@ -43,6 +43,9 @@ What's new - New command for forward search with SumatraPDF without the need of an external DDE program (requires SumatraPDF version 1.9 or higher). +- When a command takes too long to complete, ask the user for what to do + instead of automatically stopping it after a timeout interval (bug 8032). + * DOCUMENTATION AND LOCALIZATION -- 2.39.5