Przeglądaj źródła

Merge branch 'cli-timeout' of https://github.com/saschazelzer/CTK into 376-handle-timeout-retrieving-xml

Conflicts:
	Libs/CommandLineModules/Backend/LocalProcess/ctkCmdLineModuleBackendLocalProcess.cpp
	Libs/CommandLineModules/Core/ctkCmdLineModuleManager.cpp
	Libs/CommandLineModules/Core/ctkCmdLineModuleManager.h
	Libs/CommandLineModules/Core/ctkCmdLineModuleTimeoutException.cpp
	Libs/CommandLineModules/Core/ctkCmdLineModuleTimeoutException.h
Matt Clarkson 11 lat temu
rodzic
commit
a932ae4399
27 zmienionych plików z 266 dodań i 89 usunięć
  1. 1 0
      Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerConstants.cpp
  2. 1 0
      Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerConstants.h
  3. 8 1
      Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerGeneralModuleSettings.cpp
  4. 6 1
      Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerGeneralModuleSettings.h
  5. 30 10
      Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerGeneralModuleSettings.ui
  6. 6 5
      Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerMainWindow.cpp
  7. 6 2
      Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerModulesSettings.cpp
  8. 23 11
      Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerUtils.cpp
  9. 2 2
      Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerUtils.h
  10. 1 1
      Libs/CommandLineModules/Backend/FunctionPointer/ctkCmdLineModuleBackendFunctionPointer.cpp
  11. 1 1
      Libs/CommandLineModules/Backend/FunctionPointer/ctkCmdLineModuleBackendFunctionPointer.h
  12. 5 18
      Libs/CommandLineModules/Backend/LocalProcess/ctkCmdLineModuleBackendLocalProcess.cpp
  13. 1 1
      Libs/CommandLineModules/Backend/LocalProcess/ctkCmdLineModuleBackendLocalProcess.h
  14. 1 1
      Libs/CommandLineModules/Backend/XMLChecker/ctkCmdLineModuleBackendXMLChecker.cpp
  15. 1 1
      Libs/CommandLineModules/Backend/XMLChecker/ctkCmdLineModuleBackendXMLChecker.h
  16. 1 1
      Libs/CommandLineModules/Core/Testing/Cpp/ctkCmdLineModuleManagerTest.cpp
  17. 8 0
      Libs/CommandLineModules/Core/ctkCmdLineModuleBackend.cpp
  18. 14 2
      Libs/CommandLineModules/Core/ctkCmdLineModuleBackend.h
  19. 13 3
      Libs/CommandLineModules/Core/ctkCmdLineModuleConcurrentHelpers.cpp
  20. 1 1
      Libs/CommandLineModules/Core/ctkCmdLineModuleFrontend.h
  21. 19 4
      Libs/CommandLineModules/Core/ctkCmdLineModuleManager.cpp
  22. 18 0
      Libs/CommandLineModules/Core/ctkCmdLineModuleManager.h
  23. 11 0
      Libs/CommandLineModules/Core/ctkCmdLineModuleRunException.cpp
  24. 3 3
      Libs/CommandLineModules/Core/ctkCmdLineModuleRunException.h
  25. 55 8
      Libs/CommandLineModules/Core/ctkCmdLineModuleTimeoutException.cpp
  26. 29 11
      Libs/CommandLineModules/Core/ctkCmdLineModuleTimeoutException.h
  27. 1 1
      Libs/CommandLineModules/Frontend/QtGui/Testing/Cpp/ctkCmdLineModuleFrontendQtGuiTest.cpp

+ 1 - 0
Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerConstants.cpp

@@ -25,3 +25,4 @@ const QString ctkCmdLineModuleExplorerConstants::KEY_SEARCH_PATHS = "ModuleSearc
 const QString ctkCmdLineModuleExplorerConstants::KEY_REGISTERED_MODULES = "RegisteredModules";
 
 const QString ctkCmdLineModuleExplorerConstants::KEY_MAX_PARALLEL_MODULES = "MaxParallelModules";
+const QString ctkCmdLineModuleExplorerConstants::KEY_XML_TIMEOUT_SECONDS = "XmlTimeoutSeconds";

+ 1 - 0
Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerConstants.h

@@ -30,6 +30,7 @@ struct ctkCmdLineModuleExplorerConstants
   static const QString KEY_REGISTERED_MODULES;
 
   static const QString KEY_MAX_PARALLEL_MODULES;
+  static const QString KEY_XML_TIMEOUT_SECONDS;
 };
 
 #endif // CTKCMDLINEMODULEEXPLORERCONSTANTS_H

+ 8 - 1
Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerGeneralModuleSettings.cpp

@@ -20,21 +20,28 @@
 =============================================================================*/
 
 #include "ctkCmdLineModuleExplorerGeneralModuleSettings.h"
+#include "ctkCmdLineModuleManager.h"
 #include "ctkCmdLineModuleExplorerConstants.h"
 
 #include <QThreadPool>
 #include <QSettings>
 
-ctkCmdLineModuleExplorerGeneralModuleSettings::ctkCmdLineModuleExplorerGeneralModuleSettings()
+ctkCmdLineModuleExplorerGeneralModuleSettings::ctkCmdLineModuleExplorerGeneralModuleSettings(ctkCmdLineModuleManager* cmdLineModuleManager)
+  : CmdLineModuleManager(cmdLineModuleManager)
 {
   this->setupUi(this);
 
   this->registerProperty(ctkCmdLineModuleExplorerConstants::KEY_MAX_PARALLEL_MODULES,
                          this->MaxParallelModules, "value", SIGNAL(valueChanged(int)));
+  this->registerProperty(ctkCmdLineModuleExplorerConstants::KEY_XML_TIMEOUT_SECONDS,
+                         this->XmlTimeout, "value", SIGNAL(valueChanged(int)));
 }
 
 void ctkCmdLineModuleExplorerGeneralModuleSettings::applySettings()
 {
   int maxParallelModules = this->propertyValue(ctkCmdLineModuleExplorerConstants::KEY_MAX_PARALLEL_MODULES).toInt();
   QThreadPool::globalInstance()->setMaxThreadCount(maxParallelModules);
+
+  int timeout = this->propertyValue(ctkCmdLineModuleExplorerConstants::KEY_XML_TIMEOUT_SECONDS).toInt();
+  this->CmdLineModuleManager->setXmlTimeout(timeout*1000);
 }

+ 6 - 1
Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerGeneralModuleSettings.h

@@ -26,6 +26,8 @@
 
 #include "ui_ctkCmdLineModuleExplorerGeneralModuleSettings.h"
 
+class ctkCmdLineModuleManager;
+
 class ctkCmdLineModuleExplorerGeneralModuleSettings : public ctkSettingsPanel,
     public Ui::ctkCmdLineModuleExplorerGeneralModuleSettings
 {
@@ -33,10 +35,13 @@ class ctkCmdLineModuleExplorerGeneralModuleSettings : public ctkSettingsPanel,
 
 public:
 
-  ctkCmdLineModuleExplorerGeneralModuleSettings();
+  ctkCmdLineModuleExplorerGeneralModuleSettings(ctkCmdLineModuleManager* cmdLineModuleManager);
 
   void applySettings();
 
+private:
+
+  ctkCmdLineModuleManager* CmdLineModuleManager;
 };
 
 #endif // CTKCMDLINEMODULEEXPLORERGENERALMODULESETTINGS_H

+ 30 - 10
Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerGeneralModuleSettings.ui

@@ -32,15 +32,15 @@
       <string>Run Settings</string>
      </property>
      <layout class="QGridLayout" name="gridLayout">
-      <item row="1" column="0">
-       <spacer name="verticalSpacer">
+      <item row="0" column="2">
+       <spacer name="horizontalSpacer">
         <property name="orientation">
-         <enum>Qt::Vertical</enum>
+         <enum>Qt::Horizontal</enum>
         </property>
         <property name="sizeHint" stdset="0">
          <size>
-          <width>20</width>
-          <height>40</height>
+          <width>40</width>
+          <height>20</height>
          </size>
         </property>
        </spacer>
@@ -74,19 +74,39 @@
         </property>
        </widget>
       </item>
-      <item row="0" column="2">
-       <spacer name="horizontalSpacer">
+      <item row="2" column="0">
+       <spacer name="verticalSpacer">
         <property name="orientation">
-         <enum>Qt::Horizontal</enum>
+         <enum>Qt::Vertical</enum>
         </property>
         <property name="sizeHint" stdset="0">
          <size>
-          <width>40</width>
-          <height>20</height>
+          <width>20</width>
+          <height>40</height>
          </size>
         </property>
        </spacer>
       </item>
+      <item row="1" column="0">
+       <widget class="QLabel" name="label_2">
+        <property name="text">
+         <string>XML retrieval timeout (in seconds):</string>
+        </property>
+       </widget>
+      </item>
+      <item row="1" column="1">
+       <widget class="QSpinBox" name="XmlTimeout">
+        <property name="minimum">
+         <number>-1</number>
+        </property>
+        <property name="maximum">
+         <number>999999999</number>
+        </property>
+        <property name="value">
+         <number>30</number>
+        </property>
+       </widget>
+      </item>
      </layout>
     </widget>
    </item>

+ 6 - 5
Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerMainWindow.cpp

@@ -138,8 +138,8 @@ ctkCLModuleExplorerMainWindow::ctkCLModuleExplorerMainWindow(QWidget *parent) :
   }
 
   // Register persistent modules
-  QFuture<void> future = QtConcurrent::mapped(settings.value(ctkCmdLineModuleExplorerConstants::KEY_REGISTERED_MODULES).toStringList(),
-                                              ctkCmdLineModuleConcurrentRegister(&moduleManager, true));
+  QFuture<ctkCmdLineModuleReference> future = QtConcurrent::mapped(settings.value(ctkCmdLineModuleExplorerConstants::KEY_REGISTERED_MODULES).toStringList(),
+                                                                   ctkCmdLineModuleConcurrentRegister(&moduleManager, true));
 
   // Start watching directories
   directoryWatcher.setDebug(true);
@@ -149,7 +149,8 @@ ctkCLModuleExplorerMainWindow::ctkCLModuleExplorerMainWindow(QWidget *parent) :
 
   pollPauseTimer.start();
 
-  future.waitForFinished();
+  //ctkCmdLineModuleExplorerUtils::messageBoxModuleRegistration(future,
+  //                                                            moduleManager.validationMode());
 }
 
 
@@ -264,7 +265,7 @@ void ctkCLModuleExplorerMainWindow::on_actionOptions_triggered()
     settingsDialog = new ctkSettingsDialog(this);
     settings.restoreState(settingsDialog->objectName(), *settingsDialog);
     settingsDialog->setSettings(&settings);
-    ctkSettingsPanel* generalModulePanel = new ctkCmdLineModuleExplorerGeneralModuleSettings();
+    ctkSettingsPanel* generalModulePanel = new ctkCmdLineModuleExplorerGeneralModuleSettings(&moduleManager);
     settingsDialog->addPanel(generalModulePanel);
     settingsDialog->addPanel(new ctkCmdLineModuleExplorerDirectorySettings(&directoryWatcher), generalModulePanel);
     settingsDialog->addPanel(new ctkCmdLineModuleExplorerModulesSettings(&moduleManager), generalModulePanel);
@@ -284,7 +285,7 @@ void ctkCLModuleExplorerMainWindow::on_actionLoad_triggered()
   future.waitForFinished();
   this->unsetCursor();
 
-  ctkCmdLineModuleExplorerUtils::messageBoxModuleRegistration(fileNames, future.results(),
+  ctkCmdLineModuleExplorerUtils::messageBoxModuleRegistration(future,
                                                               this->moduleManager.validationMode());
 }
 

+ 6 - 2
Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerModulesSettings.cpp

@@ -83,14 +83,18 @@ void ctkCmdLineModuleExplorerModulesSettings::applySettings()
   this->setCursor(Qt::BusyCursor);
 
   QFuture<void> future1 = QtConcurrent::mapped(removedModules, ctkCmdLineModuleConcurrentUnRegister(this->ModuleManager));
-  QFuture<ctkCmdLineModuleReference> future2 = QtConcurrent::mapped(addedModules, ctkCmdLineModuleConcurrentRegister(this->ModuleManager));
+  QFuture<ctkCmdLineModuleReference> future2 = QtConcurrent::mapped(addedModules, ctkCmdLineModuleConcurrentRegister(this->ModuleManager, true));
 
   ctkSettingsPanel::applySettings();
 
+  future1.waitForFinished();
+
+  /*
   QFutureSynchronizer<void> sync;
   sync.addFuture(future1);
   sync.addFuture(future2);
   sync.waitForFinished();
+*/
 
   this->ModulesRegistered = true;
   this->pathsAdded(addedModules);
@@ -98,7 +102,7 @@ void ctkCmdLineModuleExplorerModulesSettings::applySettings()
 
   this->unsetCursor();
 
-  ctkCmdLineModuleExplorerUtils::messageBoxModuleRegistration(addedModules, future2.results(),
+  ctkCmdLineModuleExplorerUtils::messageBoxModuleRegistration(future2,
                                                               this->ModuleManager->validationMode());
 
 }

+ 23 - 11
Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerUtils.cpp

@@ -20,6 +20,7 @@
 =============================================================================*/
 
 #include "ctkCmdLineModuleExplorerUtils.h"
+#include "ctkCmdLineModuleRunException.h"
 
 #include <QPainter>
 #include <QObject>
@@ -39,23 +40,34 @@ QPixmap ctkCmdLineModuleExplorerUtils::createIconOverlay(const QPixmap &base, co
   return result;
 }
 
-void ctkCmdLineModuleExplorerUtils:: messageBoxModuleRegistration(const QStringList& modulePaths,
-                                                                 const QList<ctkCmdLineModuleReference>& moduleRefs,
-                                                                 ctkCmdLineModuleManager::ValidationMode validationMode)
+void ctkCmdLineModuleExplorerUtils::messageBoxModuleRegistration(const QFuture<ctkCmdLineModuleReference>& moduleRefsFuture,
+                                                                  ctkCmdLineModuleManager::ValidationMode validationMode)
 {
-  Q_ASSERT(modulePaths.size() == moduleRefs.size());
-
   QString errorMsg;
-  for(int i = 0; i < modulePaths.size(); ++i)
+  QFutureIterator<ctkCmdLineModuleReference> futureIter(moduleRefsFuture);
+  while(futureIter.hasNext())
   {
-    if (!moduleRefs.at(i))
+    try
     {
-      errorMsg += QObject::tr("Failed to register ") + modulePaths.at(i) + "\n\n";
-    }
-    else if (!moduleRefs.at(i).xmlValidationErrorString().isEmpty() &&
+      const ctkCmdLineModuleReference& moduleRef = futureIter.next();
+      if (!moduleRef)
+      {
+        errorMsg += QObject::tr("Failed to register ") + moduleRef.location().toString() + "\n\n";
+      }
+      else if (!moduleRef.xmlValidationErrorString().isEmpty() &&
              validationMode == ctkCmdLineModuleManager::STRICT_VALIDATION)
+      {
+        errorMsg += QObject::tr("Failed to register ") + moduleRef.location().toString() + ":\n" + moduleRef.xmlValidationErrorString() + "\n\n";
+      }
+    }
+    catch (const ctkCmdLineModuleRunException& e)
+    {
+      errorMsg += QObject::tr("Failed to register module ") + e.location().toString() + ":\n" + e.message() + "\n\\n";
+    }
+
+    catch (const std::exception& e)
     {
-      errorMsg += QObject::tr("Failed to register ") + modulePaths.at(i) + ":\n" + moduleRefs.at(i).xmlValidationErrorString() + "\n\n";
+      errorMsg += QObject::tr("Failed to register module:\n") + e.what() + "\n\n";
     }
   }
 

+ 2 - 2
Applications/ctkCommandLineModuleExplorer/ctkCmdLineModuleExplorerUtils.h

@@ -25,14 +25,14 @@
 #include "ctkCmdLineModuleManager.h"
 
 #include <QPixmap>
+#include <QFuture>
 
 struct ctkCmdLineModuleExplorerUtils
 {
 
   static QPixmap createIconOverlay(const QPixmap& base, const QPixmap& overlay);
 
-  static void messageBoxModuleRegistration(const QStringList& modulePaths,
-                                           const QList<ctkCmdLineModuleReference>& moduleRefs,
+  static void messageBoxModuleRegistration(const QFuture<ctkCmdLineModuleReference>& moduleRefsFuture,
                                            ctkCmdLineModuleManager::ValidationMode validationMode);
 
 };

+ 1 - 1
Libs/CommandLineModules/Backend/FunctionPointer/ctkCmdLineModuleBackendFunctionPointer.cpp

@@ -230,7 +230,7 @@ qint64 ctkCmdLineModuleBackendFunctionPointer::timeStamp(const QUrl &location) c
 }
 
 //----------------------------------------------------------------------------
-QByteArray ctkCmdLineModuleBackendFunctionPointer::rawXmlDescription(const QUrl& location)
+QByteArray ctkCmdLineModuleBackendFunctionPointer::rawXmlDescription(const QUrl& location, int /*timeout*/)
 {
   if (!d->UrlToFpDescription.contains(location)) return QByteArray();
   //qDebug() << d->UrlToFpDescription[location].d->xmlDescription();

+ 1 - 1
Libs/CommandLineModules/Backend/FunctionPointer/ctkCmdLineModuleBackendFunctionPointer.h

@@ -150,7 +150,7 @@ public:
 
   virtual qint64 timeStamp(const QUrl &location) const;
 
-  virtual QByteArray rawXmlDescription(const QUrl& location);
+  virtual QByteArray rawXmlDescription(const QUrl& location, int timeout);
 
   QList<QUrl> registeredFunctionPointers() const;
 

+ 5 - 18
Libs/CommandLineModules/Backend/LocalProcess/ctkCmdLineModuleBackendLocalProcess.cpp

@@ -183,33 +183,20 @@ qint64 ctkCmdLineModuleBackendLocalProcess::timeStamp(const QUrl &location) cons
 }
 
 //----------------------------------------------------------------------------
-void ctkCmdLineModuleBackendLocalProcess::setTimeOutForXMLRetrieval(const int& timeOut)
-{
-  d->setTimeOutForXMLRetrieval(timeOut);
-}
-
-//----------------------------------------------------------------------------
-int ctkCmdLineModuleBackendLocalProcess::timeOutForXMLRetrieval()
-{
-  return d->timeOutForXMLRetrieval();
-}
-
-//----------------------------------------------------------------------------
-QByteArray ctkCmdLineModuleBackendLocalProcess::rawXmlDescription(const QUrl &location)
+QByteArray ctkCmdLineModuleBackendLocalProcess::rawXmlDescription(const QUrl &location, int timeout)
 {
   QProcess process;
   process.setReadChannel(QProcess::StandardOutput);
   process.start(location.toLocalFile(), QStringList("--xml"));
 
-  if (!process.waitForFinished(d->timeOutForXMLRetrieval()) || process.exitStatus() == QProcess::CrashExit ||
-      process.error() != QProcess::UnknownError)
+  if (!process.waitForFinished(timeout))
   {
     if (process.error() == QProcess::Timedout)
     {
-      QString msg = QString("Process %1 ran for longer than the time-out threshold of %2").arg(location.toString()).arg(d->timeOutForXMLRetrieval());
-      throw ctkCmdLineModuleTimeoutException(msg);
+      throw ctkCmdLineModuleTimeoutException(location, process.errorString());
     }
-    else
+    else if (process.exitStatus() == QProcess::CrashExit ||
+             process.error() != QProcess::UnknownError)
     {
       throw ctkCmdLineModuleRunException(location, process.exitCode(), process.errorString());
     }

+ 1 - 1
Libs/CommandLineModules/Backend/LocalProcess/ctkCmdLineModuleBackendLocalProcess.h

@@ -81,7 +81,7 @@ public:
    * This method always calls the executable with a \c &ndash;&ndash;xml argument and returns
    * the complete data emitted on the standard output channel.
    */
-  virtual QByteArray rawXmlDescription(const QUrl& location);
+  virtual QByteArray rawXmlDescription(const QUrl& location, int timeout);
 
   /**
    * @brief Run a front-end for this module in a local process.

+ 1 - 1
Libs/CommandLineModules/Backend/XMLChecker/ctkCmdLineModuleBackendXMLChecker.cpp

@@ -106,7 +106,7 @@ qint64 ctkCmdLineModuleBackendXMLChecker::timeStamp(const QUrl & /*location*/) c
 
 
 //----------------------------------------------------------------------------
-QByteArray ctkCmdLineModuleBackendXMLChecker::rawXmlDescription(const QUrl& location)
+QByteArray ctkCmdLineModuleBackendXMLChecker::rawXmlDescription(const QUrl& location, int /*timeout*/)
 {
   if (location.isValid())
   {

+ 1 - 1
Libs/CommandLineModules/Backend/XMLChecker/ctkCmdLineModuleBackendXMLChecker.h

@@ -70,7 +70,7 @@ public:
    * This method always calls the executable with a \c &ndash;&ndash;xml argument and returns
    * the complete data emitted on the standard output channel.
    */
-  virtual QByteArray rawXmlDescription(const QUrl& location);
+  virtual QByteArray rawXmlDescription(const QUrl& location, int timeout);
 
   /**
    * @brief Run a front-end for this module in a local process.

+ 1 - 1
Libs/CommandLineModules/Core/Testing/Cpp/ctkCmdLineModuleManagerTest.cpp

@@ -52,7 +52,7 @@ public:
   virtual QString description() const { return "Test Mock-up"; }
   virtual QList<QString> schemes() const { return QList<QString>() << "test"; }
   virtual qint64 timeStamp(const QUrl& /*location*/) const { return 0; }
-  virtual QByteArray rawXmlDescription(const QUrl& location)
+  virtual QByteArray rawXmlDescription(const QUrl& location, int /*timeout*/)
   {
     return UrlToXml[location];
   }

+ 8 - 0
Libs/CommandLineModules/Core/ctkCmdLineModuleBackend.cpp

@@ -21,7 +21,15 @@
 
 #include "ctkCmdLineModuleBackend.h"
 
+#include <qbytearray.h>
+
 //----------------------------------------------------------------------------
 ctkCmdLineModuleBackend::~ctkCmdLineModuleBackend()
 {
 }
+
+//----------------------------------------------------------------------------
+QByteArray ctkCmdLineModuleBackend::rawXmlDescription(const QUrl& location)
+{
+  return this->rawXmlDescription(location, 30000);
+}

+ 14 - 2
Libs/CommandLineModules/Core/ctkCmdLineModuleBackend.h

@@ -46,7 +46,7 @@ class QUrl;
 struct CTK_CMDLINEMODULECORE_EXPORT ctkCmdLineModuleBackend
 {
 
-  ~ctkCmdLineModuleBackend();
+  virtual ~ctkCmdLineModuleBackend();
 
   /**
    * @brief Returns the name of the type of the backend, not the name
@@ -77,6 +77,7 @@ struct CTK_CMDLINEMODULECORE_EXPORT ctkCmdLineModuleBackend
   /**
    * @brief Get the XML parameter description from the given location.
    * @param location The location URL specifying the module.
+   * @param timeout The time-out for retrieving the XML parameter description
    * @return The raw XML parameter description.
    *
    * This method may be concurrently called by the ctkCmdLineModuleManager and
@@ -84,8 +85,19 @@ struct CTK_CMDLINEMODULECORE_EXPORT ctkCmdLineModuleBackend
    * as caching is done by the ctkCmdLineModuleManager itself, checking the
    * return value of timeStamp().
    *
+   * Implementations should also throw either a ctkCmdLineModuleTimeoutException
+   * object if a time-out occured when retrieving the XML parameter description
+   * or a ctkCmdLineModuleRunException for any other error during invocation
+   * of the module.
+   *
+   * @throws ctkCmdLineModuleTimeoutException if a time-out occurred when
+   *         retrieving the XML parameter description.
+   * @throws ctkCmdLineModuleRunException if a runtime error occurred when
+   *         invoking the module to retrieve the XML parameter description.
    */
-  virtual QByteArray rawXmlDescription(const QUrl& location) = 0;
+  virtual QByteArray rawXmlDescription(const QUrl& location, int timeout) = 0;
+  
+  QByteArray rawXmlDescription(const QUrl& location);
 
 protected:
 

+ 13 - 3
Libs/CommandLineModules/Core/ctkCmdLineModuleConcurrentHelpers.cpp

@@ -22,8 +22,9 @@
 #include "ctkCmdLineModuleConcurrentHelpers.h"
 
 #include "ctkCmdLineModuleManager.h"
-#include "ctkException.h"
+#include "ctkCmdLineModuleRunException.h"
 
+#include <qtconcurrentexception.h>
 #include <QUrl>
 #include <QDebug>
 
@@ -46,13 +47,21 @@ ctkCmdLineModuleReference ctkCmdLineModuleConcurrentRegister::operator()(const Q
   {
     return this->ModuleManager->registerModule(moduleUrl);
   }
+  catch (const QtConcurrent::Exception& e)
+  {
+    if (this->Debug)
+    {
+      qDebug() << e.what();
+    }
+    throw e;
+  }
   catch (const ctkException& e)
   {
     if (this->Debug)
     {
       qDebug() << e;
     }
-    return ctkCmdLineModuleReference();
+    throw ctkCmdLineModuleRunException(moduleUrl, 0, e.what());
   }
   catch (...)
   {
@@ -60,8 +69,9 @@ ctkCmdLineModuleReference ctkCmdLineModuleConcurrentRegister::operator()(const Q
     {
       qDebug() << "Registering module" << moduleUrl << "failed with an unknown exception.";
     }
-    return ctkCmdLineModuleReference();
+    throw ctkCmdLineModuleRunException(moduleUrl, 0, "Unknown exception");
   }
+  return ctkCmdLineModuleReference();
 }
 
 //----------------------------------------------------------------------------

+ 1 - 1
Libs/CommandLineModules/Core/ctkCmdLineModuleFrontend.h

@@ -100,7 +100,7 @@ public:
   };
   Q_DECLARE_FLAGS(ParameterFilters, ParameterFilter)
 
-  ~ctkCmdLineModuleFrontend();
+  virtual ~ctkCmdLineModuleFrontend();
 
   /**
    * @brief Returns the GUI representation.

+ 19 - 4
Libs/CommandLineModules/Core/ctkCmdLineModuleManager.cpp

@@ -23,6 +23,7 @@
 
 #include "ctkCmdLineModuleBackend.h"
 #include "ctkCmdLineModuleFrontend.h"
+#include "ctkCmdLineModuleTimeoutException.h"
 #include "ctkCmdLineModuleCache_p.h"
 #include "ctkCmdLineModuleFuture.h"
 #include "ctkCmdLineModuleXmlValidator.h"
@@ -53,7 +54,8 @@ extern int qHash(const QUrl& url);
 struct ctkCmdLineModuleManagerPrivate
 {
   ctkCmdLineModuleManagerPrivate(ctkCmdLineModuleManager::ValidationMode mode, const QString& cacheDir)
-    : ValidationMode(mode)
+    : XmlTimeOut(30000)
+    , ValidationMode(mode)
   {
     QFileInfo fileInfo(cacheDir);
     if (!fileInfo.exists())
@@ -87,6 +89,7 @@ struct ctkCmdLineModuleManagerPrivate
   QHash<QString, ctkCmdLineModuleBackend*> SchemeToBackend;
   QHash<QUrl, ctkCmdLineModuleReference> LocationToRef;
   QScopedPointer<ctkCmdLineModuleCache> ModuleCache;
+  int XmlTimeOut;
 
   ctkCmdLineModuleManager::ValidationMode ValidationMode;
 };
@@ -117,6 +120,17 @@ void ctkCmdLineModuleManager::setValidationMode(const ValidationMode& mode)
 
 
 //----------------------------------------------------------------------------
+void ctkCmdLineModuleManager::setXmlTimeout(int xmlTimeout)
+{
+  d->XmlTimeOut = xmlTimeout;
+}
+
+//----------------------------------------------------------------------------
+int ctkCmdLineModuleManager::xmlTimeout() const
+{
+  return d->XmlTimeOut;
+}
+//----------------------------------------------------------------------------
 void ctkCmdLineModuleManager::registerBackend(ctkCmdLineModuleBackend *backend)
 {
   QMutexLocker lock(&d->Mutex);
@@ -209,11 +223,12 @@ ctkCmdLineModuleManager::registerModule(const QUrl &location)
       // newly fetch the XML description
       try
       {
-        xml = backend->rawXmlDescription(location);
+        xml = backend->rawXmlDescription(location, d->XmlTimeOut);
       }
-      catch (const ctkCmdLineModuleTimeoutException& e)
+      catch (const ctkCmdLineModuleTimeoutException&)
       {
-        qDebug() << "Extracting XML from " << location.toString() << " timed-out, with message:" << e.what();
+        // in case of a time-out, do not cache it as a failed attempt
+        // by recording an empty QByteArray in the cache
         throw;
       }
       catch (...)

+ 18 - 0
Libs/CommandLineModules/Core/ctkCmdLineModuleManager.h

@@ -111,6 +111,21 @@ public:
   void setValidationMode(const ValidationMode& mode);
 
   /**
+   * @brief Set the timeout for retrieving the XML parameter description from a module.
+   *
+   * The default time-out is 30 seconds.
+   *
+   * @param xmlTimeout The timeout in milli seconds.
+   */
+  void setXmlTimeout(int xmlTimeout);
+
+  /**
+   * @brief Get the timeout for retrieving the XML parameter description from a ´module.
+   * @return The timeout in milli seconds.
+   */
+  int xmlTimeout() const;
+
+  /**
    * @brief Registers a new back-end.
    * @param backend The new back-end.
    * @throws ctkInvalidArgumentException if another back-end was already registered handling
@@ -132,6 +147,9 @@ public:
    * @return A module reference.
    * @throws ctkInvalidArgumentException if no back-end for the given URL scheme was registered
    *         or the XML description for the module is invalid.
+   * @throws ctkCmdLineModuleTimeoutException if a time-out occured when retrieving the
+   *         XML description from the module.
+   * @throws ctkCmdLineModuleRunException if a general error occurred when running the module.
    */
   ctkCmdLineModuleReference registerModule(const QUrl& location);
 

+ 11 - 0
Libs/CommandLineModules/Core/ctkCmdLineModuleRunException.cpp

@@ -47,6 +47,17 @@ ctkCmdLineModuleRunException::ctkCmdLineModuleRunException(const ctkCmdLineModul
 }
 
 //----------------------------------------------------------------------------
+ctkCmdLineModuleRunException& ctkCmdLineModuleRunException::operator=(const ctkCmdLineModuleRunException& o)
+{
+  QtConcurrent::Exception::operator=(o);
+  ctkException::operator=(o);
+  this->Location = o.Location;
+  this->ErrorCode = o.ErrorCode;
+  this->ErrorString = o.ErrorString;
+  return *this;
+}
+
+//----------------------------------------------------------------------------
 ctkCmdLineModuleRunException::~ctkCmdLineModuleRunException() throw()
 {
 }

+ 3 - 3
Libs/CommandLineModules/Core/ctkCmdLineModuleRunException.h

@@ -68,9 +68,9 @@ public:
 
 private:
 
-  const QUrl Location;
-  const int ErrorCode;
-  const QString ErrorString;
+  QUrl Location;
+  int ErrorCode;
+  QString ErrorString;
 
 };
 

+ 55 - 8
Libs/CommandLineModules/Core/ctkCmdLineModuleTimeoutException.cpp

@@ -1,23 +1,70 @@
 /*=============================================================================
-
+  
   Library: CTK
-
-  Copyright (c) University College London
-
+  
+  Copyright (c) German Cancer Research Center,
+    Division of Medical and Biological Informatics
+    
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at
-
+  
     http://www.apache.org/licenses/LICENSE-2.0
-
+    
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
-
+  
 =============================================================================*/
 
 #include "ctkCmdLineModuleTimeoutException.h"
 
-CTK_IMPLEMENT_EXCEPTION(ctkCmdLineModuleTimeoutException, ctkException, "Command Line Module time-out exception")
+//----------------------------------------------------------------------------
+ctkCmdLineModuleTimeoutException::ctkCmdLineModuleTimeoutException(const QUrl &location, const QString &errorString)
+  : ctkCmdLineModuleRunException(location, -1, errorString)
+{
+}
+
+//----------------------------------------------------------------------------
+ctkCmdLineModuleTimeoutException::ctkCmdLineModuleTimeoutException(const QUrl &location, const QString &errorString,
+    const ctkCmdLineModuleRunException& cause)
+  : ctkCmdLineModuleRunException(location, -1, errorString, cause)
+{
+}
+
+//----------------------------------------------------------------------------
+ctkCmdLineModuleTimeoutException::~ctkCmdLineModuleTimeoutException() throw()
+{
+}
+
+//----------------------------------------------------------------------------
+const char* ctkCmdLineModuleTimeoutException::name() const throw()
+{
+  return "CTK CommandLineModule Timeout Exception";
+}
+
+//----------------------------------------------------------------------------
+const char* ctkCmdLineModuleTimeoutException::className() const throw()
+{
+  return "ctkCmdLineModuleTimeoutException";
+}
+
+//----------------------------------------------------------------------------
+ctkCmdLineModuleTimeoutException* ctkCmdLineModuleTimeoutException::clone() const
+{
+  return new ctkCmdLineModuleTimeoutException(*this);
+}
+
+//----------------------------------------------------------------------------
+void ctkCmdLineModuleTimeoutException::rethrow() const
+{
+  throw *this;
+}
+
+//----------------------------------------------------------------------------
+void ctkCmdLineModuleTimeoutException::raise() const
+{
+  throw *this;
+}

+ 29 - 11
Libs/CommandLineModules/Core/ctkCmdLineModuleTimeoutException.h

@@ -1,35 +1,53 @@
 /*=============================================================================
-
+  
   Library: CTK
-
-  Copyright (c) University College London
-
+  
+  Copyright (c) German Cancer Research Center,
+    Division of Medical and Biological Informatics
+    
   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at
-
+  
     http://www.apache.org/licenses/LICENSE-2.0
-
+    
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
-
 =============================================================================*/
 
 #ifndef CTKCMDLINEMODULETIMEOUTEXCEPTION_H
 #define CTKCMDLINEMODULETIMEOUTEXCEPTION_H
 
-#include <ctkException.h>
-
+#include <ctkCmdLineModuleRunException.h>
 #include "ctkCommandLineModulesCoreExport.h"
 
 /**
  * \class ctkCmdLineModuleTimeoutException
- * \brief Exception class to describe problems with time-outs.
+ * \brief Exception class to describe problems with timeouts when running a module.
  * \ingroup CommandLineModulesCore_API
  */
-CTK_DECLARE_EXCEPTION(CTK_CMDLINEMODULECORE_EXPORT, ctkCmdLineModuleTimeoutException, ctkException)
+class CTK_CMDLINEMODULECORE_EXPORT ctkCmdLineModuleTimeoutException
+    : public ctkCmdLineModuleRunException
+{
+public:
+
+  explicit ctkCmdLineModuleTimeoutException(const QUrl& location, const QString& errorString);
+
+  ctkCmdLineModuleTimeoutException(const QUrl& location, const QString& errorString,
+                                   const ctkCmdLineModuleRunException& cause);
+
+  ~ctkCmdLineModuleTimeoutException() throw();
+
+  virtual const char* name() const throw();
+  virtual const char* className() const throw();
+  virtual ctkCmdLineModuleTimeoutException* clone() const;
+  virtual void rethrow() const;
+
+  virtual void raise() const;
+
+};
 
 #endif // CTKCMDLINEMODULETIMEOUTEXCEPTION_H

+ 1 - 1
Libs/CommandLineModules/Frontend/QtGui/Testing/Cpp/ctkCmdLineModuleFrontendQtGuiTest.cpp

@@ -58,7 +58,7 @@ public:
   virtual QString description() const { return "Test Mock-up"; }
   virtual QList<QString> schemes() const { return QList<QString>() << "test"; }
   virtual qint64 timeStamp(const QUrl& /*location*/) const { return 0; }
-  virtual QByteArray rawXmlDescription(const QUrl& location)
+  virtual QByteArray rawXmlDescription(const QUrl& location, int /*timeout*/)
   {
     return UrlToXml[location];
   }