[prev in list] [next in list] [prev in thread] [next in thread]
List: lyx-devel
Subject: Re: Canceling Background Export
From: Peter_Kümmel <syntheticpp () gmx ! net>
Date: 2011-11-08 20:44:27
Message-ID: 4EB994AB.4080803 () gmx ! net
[Download RAW message or body]
> Some version of this strategy seems necessary, since one possible reason
> to want to stop the export thread is that one of the converters is in an
> infinite loop. Since we depend on external converters, this kind of
> thing can easily happen and not be under our control. (Of course none of
> the LyX converters would ever behave so badly!)
>
> Here's an idea that might work within the current framework:
>
> 1. Send a signal to the background export thread, which it will
> presumably process no matter what else it might be doing.
Event loop is blocked of the background task. We should change
the implementation of Systemcall to a asynchronous one (no sleep and no processEvents).
> 2. Kill whatever external processes have been started for image
> conversion, etc, and set some kind of boolean so that no more will be
> started while we're at it.
Already done, but we must not kill all available processes. Maybe we
could use the thread pointer to select the correct processes.
> 3. Finally, set another boolean as a signal to the main export routine
> that it should abort. This can be checked when convenient, since my
> sense is that this backend export is not what is expensive.
See the 'extern bool isProcessingEnabled;' hack in attached patch.
It already feels a bit snappier.
Peter
>
> Peter's patch does something along these lines, but at the wrong level,
> it seems to me. We don't want to disable ALL background processing, I
> wouldn't have thought, since that might include image conversions
> demanded by the main thread. And we wouldn't want to kill all background
> processes, for the same reason.
>
> Richard
>
["abort.patch" (text/x-patch)]
Index: src/Converter.cpp
===================================================================
--- src/Converter.cpp (revision 40157)
+++ src/Converter.cpp (working copy)
@@ -348,6 +348,12 @@
FileName outfile = from_file;
for (Graph::EdgePath::const_iterator cit = edgepath.begin();
cit != edgepath.end(); ++cit) {
+
+ extern bool isProcessingEnabled;
+ if (!isProcessingEnabled) {
+ return false;
+ }
+
Converter const & conv = converterlist_[*cit];
bool dummy = conv.To->dummy() && conv.to != "program";
if (!dummy) {
Index: src/frontends/qt4/GuiProgress.cpp
===================================================================
--- src/frontends/qt4/GuiProgress.cpp (revision 40157)
+++ src/frontends/qt4/GuiProgress.cpp (working copy)
@@ -184,7 +184,12 @@
QMessageBox::information(qApp->focusWidget(), title, message);
}
+void GuiProgress::abortAllProcessesClicked()
+{
+ abortAndDisableProcessing();
+}
+
} // namespace frontend
} // namespace lyx
Index: src/frontends/qt4/GuiProgress.h
===================================================================
--- src/frontends/qt4/GuiProgress.h (revision 40157)
+++ src/frontends/qt4/GuiProgress.h (working copy)
@@ -54,7 +54,6 @@
void clearMessages();
void appendLyXErrMessage(QString const & text);
-
void clearMessageText();
void updateStatusBarMessage(QString const &);
void triggerFlush();
@@ -76,6 +75,7 @@
void doToggleWarning(QString const & title, QString const & msg, QString const & \
formatted); void doError(QString const &, QString const &);
void doInformation(QString const &, QString const &);
+ void abortAllProcessesClicked();
void updateWithLyXErr();
void startFlushing();
Index: src/frontends/qt4/GuiView.cpp
===================================================================
--- src/frontends/qt4/GuiView.cpp (revision 40157)
+++ src/frontends/qt4/GuiView.cpp (working copy)
@@ -249,6 +249,15 @@
dynamic_cast<GuiProgress*>(progress_),
SIGNAL(clearMessageText()),
gv, SLOT(clearMessageText()));
+
+ // fit into LyX
+ QPushButton* abortButton = new QPushButton();
+ abortButton->setText("Abort processes");
+ abortButton->show();
+
+ // Forward abort signal down to SystemCall via ProgressInterface.
+ connect(abortButton, SIGNAL(clicked()),
+ dynamic_cast<GuiProgress*>(progress_), \
SLOT(abortAllProcessesClicked())); }
~GuiViewPrivate()
@@ -554,6 +563,9 @@
break;
}
view->message(msg);
+ if (ProgressInterface::instance()) {
+ ProgressInterface::instance()->enableProcessing();
+ }
}
Index: src/output_latex.cpp
===================================================================
--- src/output_latex.cpp (revision 40157)
+++ src/output_latex.cpp (working copy)
@@ -685,7 +685,9 @@
// FIXME UNICODE
os << from_utf8(everypar);
- par.latex(bparams, outerfont, os, runparams, start_pos, end_pos);
+ if (!par.latex(bparams, outerfont, os, runparams, start_pos, end_pos)) {
+ return;
+ }
// Make sure that \\par is done with the font of the last
// character if this has another size as the default.
Index: src/Paragraph.cpp
===================================================================
--- src/Paragraph.cpp (revision 40157)
+++ src/Paragraph.cpp (working copy)
@@ -2278,7 +2278,7 @@
// This one spits out the text of the paragraph
-void Paragraph::latex(BufferParams const & bparams,
+bool Paragraph::latex(BufferParams const & bparams,
Font const & outerfont,
otexstream & os,
OutputParams const & runparams,
@@ -2292,7 +2292,7 @@
bparams.documentClass().plainLayout() : *d->layout_;
if (!force && style.inpreamble)
- return;
+ return true;;
bool const allowcust = allowParagraphCustomization();
@@ -2339,7 +2339,14 @@
column += d->startTeXParParams(bparams, os, runparams);
}
+
for (pos_type i = 0; i < size(); ++i) {
+
+ extern bool isProcessingEnabled;
+ if (!isProcessingEnabled) {
+ return false;
+ }
+
// First char in paragraph or after label?
if (i == body_pos) {
if (body_pos > 0) {
@@ -2525,6 +2532,8 @@
// Set the encoding to that returned from latexSpecialChar (see
// comment for encoding member in OutputParams.h)
runparams.encoding = rp.encoding;
+
+ return true;
}
// If we have an open font definition, we have to close it
@@ -2563,6 +2572,8 @@
}
LYXERR(Debug::LATEX, "Paragraph::latex... done " << this);
+
+ return true;
}
Index: src/Paragraph.h
===================================================================
--- src/Paragraph.h (revision 40157)
+++ src/Paragraph.h (working copy)
@@ -191,7 +191,7 @@
void validate(LaTeXFeatures &) const;
/// \param force means: output even if layout.inpreamble is true.
- void latex(BufferParams const &, Font const & outerfont, otexstream &,
+ bool latex(BufferParams const &, Font const & outerfont, otexstream &,
OutputParams const &, int start_pos = 0, int end_pos = -1,
bool force = false) const;
Index: src/support/ProgressInterface.h
===================================================================
--- src/support/ProgressInterface.h (revision 40157)
+++ src/support/ProgressInterface.h (working copy)
@@ -30,6 +30,7 @@
virtual void appendError(QString const &) = 0;
virtual void clearMessages() = 0;
virtual void lyxerrFlush() = 0;
+ void abortAndDisbaleProcessing();
/// Alert interface
virtual void warning(QString const & title, QString const & message) = 0;
@@ -43,6 +44,10 @@
static void setInstance(ProgressInterface*);
static ProgressInterface* instance();
+ // calls from Gui into SystemCall
+ void abortAndDisableProcessing();
+ void enableProcessing();
+
protected:
ProgressInterface() {}
};
Index: src/support/Systemcall.cpp
===================================================================
--- src/support/Systemcall.cpp (revision 40157)
+++ src/support/Systemcall.cpp (working copy)
@@ -32,7 +32,10 @@
#include <QThread>
#include <QCoreApplication>
#include <QDebug>
+#include <QMutexLocker>
+
+
#define USE_QPROCESS
@@ -45,6 +48,7 @@
};
+bool isProcessingEnabled = true;
using namespace std;
@@ -93,8 +97,20 @@
}
+void ProgressInterface::abortAndDisableProcessing()
+{
+ SystemcallPrivate::setProcessingEnabled(false);
+ SystemcallPrivate::killCurrentProcesses();
+}
+void ProgressInterface::enableProcessing()
+{
+ SystemcallPrivate::setProcessingEnabled(true);
+}
+
+
+
// Reuse of instance
#ifndef USE_QPROCESS
int Systemcall::startscript(Starttype how, string const & what,
@@ -236,6 +252,11 @@
{
lyxerr << "\nRunning: " << what << endl;
+ if (!SystemcallPrivate::isProcessingEnabled()) {
+ LYXERR0("Systemcall: disabled ");
+ return 30;
+ }
+
string outfile;
string errfile;
QString cmd = QString::fromLocal8Bit(
@@ -257,6 +278,8 @@
return 0;
}
+ // when we are here we know that we don't use SystemCall asynchronously
+ d.appendAsKillableProcess();
if (!d.waitWhile(SystemcallPrivate::Running, process_events,
os::timeout_min() * 60 * 1000)) {
LYXERR0("Systemcall: '" << cmd << "' did not finish!");
@@ -337,6 +360,9 @@
connect(process_, SIGNAL(finished(int, QProcess::ExitStatus)), \
SLOT(processFinished(int, QProcess::ExitStatus))); }
+bool SystemcallPrivate::is_processing_enabled_ = true;
+QMutex SystemcallPrivate::killable_processes_mutex_;
+QSet<QProcess*> SystemcallPrivate::killable_processes_;
void SystemcallPrivate::startProcess(QString const & cmd, string const & path)
{
@@ -553,6 +579,7 @@
void SystemcallPrivate::killProcess()
{
killProcess(process_);
+ removeAsKillableProcess();
}
@@ -567,8 +594,55 @@
}
}
+void SystemcallPrivate::enableProcessing()
+{
+ SystemcallPrivate::setProcessingEnabled(true);
+}
+void SystemcallPrivate::abortAndStopFurtherProcessing()
+{
+ SystemcallPrivate::setProcessingEnabled(false);
+ process_->kill();
+}
+bool SystemcallPrivate::isProcessingEnabled()
+{
+ return is_processing_enabled_;
+}
+
+
+
+void SystemcallPrivate::setProcessingEnabled(bool enable)
+{
+ is_processing_enabled_ = enable;
+ ::isProcessingEnabled = enable;
+}
+
+
+void SystemcallPrivate::appendAsKillableProcess()
+{
+ QMutexLocker lock(&killable_processes_mutex_);
+ killable_processes_.insert(process_);
+}
+
+void SystemcallPrivate::removeAsKillableProcess()
+{
+ QMutexLocker lock(&killable_processes_mutex_);
+ killable_processes_.remove(process_);
+}
+
+void SystemcallPrivate::killCurrentProcesses()
+{
+ QMutexLocker lock(&killable_processes_mutex_);
+ Q_FOREACH(QProcess* p, killable_processes_) {
+ p->kill();
+ }
+ killable_processes_.clear();
+}
+
+
+
+
#include "moc_SystemcallPrivate.cpp"
#endif
Index: src/support/SystemcallPrivate.h
===================================================================
--- src/support/SystemcallPrivate.h (revision 40157)
+++ src/support/SystemcallPrivate.h (working copy)
@@ -14,6 +14,7 @@
#include <QObject>
#include <QProcess>
+#include <QMutex>
#include <string>
@@ -55,6 +56,13 @@
static void killProcess(QProcess * p);
+ static bool isProcessingEnabled();
+ static void setProcessingEnabled(bool);
+
+ void appendAsKillableProcess();
+ void removeAsKillableProcess();
+
+ static void killCurrentProcesses();
public Q_SLOTS:
void stdOut();
@@ -62,8 +70,11 @@
void processError(QProcess::ProcessError);
void processStarted();
void processFinished(int, QProcess::ExitStatus status);
+
+ void abortAndStopFurtherProcessing();
+ void enableProcessing();
+
-
private:
/// Pointer to the process to monitor.
QProcess * process_;
@@ -91,6 +102,10 @@
void processEvents();
void killProcess();
+ static bool is_processing_enabled_;
+
+ static QMutex killable_processes_mutex_;
+ static QSet<QProcess*> killable_processes_;
};
} // namespace support
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic