# # # patch "guitone/src/monotone/Monotone.cpp" # from [36f07b16c20c0844db126fd93f333e38e1ca17ff] # to [e81b5636581b65fa974485a3fefe72ff42a0f921] # # patch "guitone/src/monotone/Monotone.h" # from [4082863bc15b609d153c0df708698b814d0d2340] # to [239d5ba68bde0ac80b44da173ac9d0ea005bb2a3] # ============================================================ --- guitone/src/monotone/Monotone.cpp 36f07b16c20c0844db126fd93f333e38e1ca17ff +++ guitone/src/monotone/Monotone.cpp e81b5636581b65fa974485a3fefe72ff42a0f921 @@ -25,6 +25,7 @@ #include #include +#include Monotone* Monotone::instance = 0; @@ -113,6 +114,45 @@ void Monotone::processTerminated(int cod emit criticalError(tr("The connection to the monotone process was terminated (Code %1). Check your configuration and reload the current workspace afterwards.").arg(code)); } +void Monotone::timedOut() +{ + timeout = true; +} + +bool Monotone::newCommandSetup() +{ + if (process->state() != QProcess::Running && !process->waitForStarted(15000)) + { + qDebug("Monotone::newCommandSetup: Process is not running"); + return false; + } + + // blocks until any previously triggered command has given up + // waiting for another process to be finished or itself processes + // its input + mutex.lock(); + + timeout = false; + // FIXME: make the timeout span configurable + QTimer::singleShot(5000, this, SLOT(timedOut())); + while(isProcessingData && !timeout) QCoreApplication::processEvents(); + + if (timeout) + { + qDebug("Monotone::newCommandSetup: Timed out waiting for other process"); + mutex.unlock(); + return false; + } + + isProcessingData = true; + input.clear(); + output.clear(); + + mutex.unlock(); + + return true; +} + bool Monotone::executeCommand(const QStringList & command, int & retCode) { QStringList opts; @@ -121,14 +161,15 @@ bool Monotone::executeCommand(const QStr bool Monotone::executeCommand(const QStringList & command, const QStringList & options, int & retCode) { - SignalWaiter waiter(process, SIGNAL(readyReadStandardOutput())); - - if (!writeStdin(command, options)) - { - qDebug("Monotone::executeCommand: could not write command to stdin"); + if (!newCommandSetup()) + { return false; } + + SignalWaiter waiter(process, SIGNAL(readyReadStandardOutput())); + writeStdin(command, options); + while (waiter.wait(1000)) { // check if we already could parse the complete stdio output @@ -155,6 +196,13 @@ bool Monotone::triggerCommand(AutomateCo bool Monotone::triggerCommand(AutomateCommand * caller, const QStringList & command, const QStringList & options) { + if (!newCommandSetup()) + { + return false; + } + + lastCaller = caller; + // read & parse mtn's output as soon as it gets available connect( process, SIGNAL(readyReadStandardOutput()), @@ -167,35 +215,19 @@ bool Monotone::triggerCommand(AutomateCo caller, SLOT(parseOutput(AutomateCommand*)) ); - lastCaller = caller; + writeStdin(command, options); - return writeStdin(command, options); + return true; } // TODO: we might want to implement a Queue for that some time so commands // are executed sequentially in the order they've come in and don't need to // wait for each other -bool Monotone::writeStdin(const QStringList & command, const QStringList & options) +void Monotone::writeStdin(const QStringList & command, const QStringList & options) { // wait until the process has been started up if it is not already // running. Notice that if waitForStartup times out after 15 seconds // the error handler is called and the program is terminated! - if (process->state() != QProcess::Running && !process->waitForStarted(15000)) - { - qDebug("Monotone::writeStdin: Process is not running"); - return false; - } - - // check if we're already processing a command - if (isProcessingData) - { - qDebug("Monotone::writeStdin: Not finished processing data"); - return false; - } - - isProcessingData = true; - input.clear(); - output.clear(); commandLine = ""; if (options.size() > 0) @@ -233,8 +265,6 @@ bool Monotone::writeStdin(const QStringL // So we need the following QTextStream QTextStream streamStdIn(process); streamStdIn << commandLine; - - return true; } void Monotone::readAndProcessCommand() @@ -319,8 +349,6 @@ bool Monotone::readAndParseStdout(int & // when subsequent data are flushed and processed here if (input.length() < outBytes) { - qDebug("%d <> %d (%s)", input.length(), outBytes, qPrintable(input)); - // prepend the data header again input.prepend(QString("%1:%2:%3:%4:") .arg(list[1]) ============================================================ --- guitone/src/monotone/Monotone.h 4082863bc15b609d153c0df708698b814d0d2340 +++ guitone/src/monotone/Monotone.h 239d5ba68bde0ac80b44da173ac9d0ea005bb2a3 @@ -24,6 +24,7 @@ #include "../model/AutomateCommand.h" #include #include +#include class Monotone : public QObject { @@ -49,9 +50,12 @@ class Monotone : public QObject private: Monotone(QObject *); - bool writeStdin(const QStringList &, const QStringList &); + bool newCommandSetup(); + void writeStdin(const QStringList &, const QStringList &); bool readAndParseStdout(int &); + QMutex mutex; + bool timeout; QString input; QString output; QString commandLine; @@ -65,6 +69,7 @@ class Monotone : public QObject void readAndProcessCommand(); void processTerminated(int, QProcess::ExitStatus); void startupError(QProcess::ProcessError); + void timedOut(); signals: void commandFinished(AutomateCommand*);