From 64efa000549d8a248ee98053a471483aeee8dacc Mon Sep 17 00:00:00 2001 From: mlangkabel Date: Tue, 29 Aug 2017 14:15:11 +0200 Subject: [PATCH] logic: improved Maven timeout policy (issue #449) * only timeout if Maven did not generate output during the last 60 seconds --- src/lib_gui/utility/utilityApp.cpp | 47 +++++++++++++++++++++++- src/lib_gui/utility/utilityApp.h | 5 ++- src/lib_java/project/SourceGroupJava.cpp | 15 +++++--- src/lib_java/utility/utilityMaven.cpp | 30 ++++++++++++--- 4 files changed, 81 insertions(+), 16 deletions(-) diff --git a/src/lib_gui/utility/utilityApp.cpp b/src/lib_gui/utility/utilityApp.cpp index b00b01a7..3c21bc3c 100644 --- a/src/lib_gui/utility/utilityApp.cpp +++ b/src/lib_gui/utility/utilityApp.cpp @@ -18,7 +18,7 @@ namespace utility std::set s_runningProcesses; } -std::string utility::executeProcess(const std::string& command, const std::string& workingDirectory, int timeout) +std::string utility::executeProcess(const std::string& command, const std::string& workingDirectory, const int timeout) { QProcess process; process.setProcessChannelMode(QProcess::MergedChannels); @@ -47,7 +47,50 @@ std::string utility::executeProcess(const std::string& command, const std::strin return processoutput; } -int utility::executeProcessAndGetExitCode(const std::string& command, const std::string& workingDirectory, int timeout) +std::string utility::executeProcessUntilNoOutput(const std::string& command, const std::string& workingDirectory, const int waitTime) +{ + QProcess process; + process.setProcessChannelMode(QProcess::MergedChannels); + + if (!workingDirectory.empty()) + { + process.setWorkingDirectory(workingDirectory.c_str()); + } + + { + std::lock_guard lock(s_runningProcessesMutex); + process.start(command.c_str()); + s_runningProcesses.insert(&process); + } + + std::string processoutput = ""; + while (!process.waitForFinished(waitTime)) + { + const std::string currentOutput = process.readAll().toStdString(); + if (currentOutput.empty()) + { + LOG_WARNING("Canceling process because it did not generate any output during the last " + std::to_string(waitTime / 1000) + " seconds."); + break; + } + else + { + processoutput += currentOutput; + } + } + + { + std::lock_guard lock(s_runningProcessesMutex); + s_runningProcesses.erase(&process); + } + + processoutput += process.readAll().toStdString(); + process.close(); + processoutput = utility::trim(processoutput); + + return processoutput; +} + +int utility::executeProcessAndGetExitCode(const std::string& command, const std::string& workingDirectory, const int timeout) { QProcess process; diff --git a/src/lib_gui/utility/utilityApp.h b/src/lib_gui/utility/utilityApp.h index fe9f9894..dab8c521 100644 --- a/src/lib_gui/utility/utilityApp.h +++ b/src/lib_gui/utility/utilityApp.h @@ -11,8 +11,9 @@ class License; namespace utility { - std::string executeProcess(const std::string& command, const std::string& workingDirectory = "", int timeout = 30000); - int executeProcessAndGetExitCode(const std::string& command, const std::string& workingDirectory = "", int timeout = 30000); + std::string executeProcess(const std::string& command, const std::string& workingDirectory = "", const int timeout = 30000); + std::string executeProcessUntilNoOutput(const std::string& command, const std::string& workingDirectory, int waitTime = 10000); + int executeProcessAndGetExitCode(const std::string& command, const std::string& workingDirectory = "", const int timeout = 30000); void killRunningProcesses(); diff --git a/src/lib_java/project/SourceGroupJava.cpp b/src/lib_java/project/SourceGroupJava.cpp index 025e65d8..6bdec23f 100644 --- a/src/lib_java/project/SourceGroupJava.cpp +++ b/src/lib_java/project/SourceGroupJava.cpp @@ -162,16 +162,19 @@ bool SourceGroupJava::prepareMavenData() "Please make sure to provide the correct Maven Path in the preferences."; MessageStatus(dialogMessage, true, false).dispatch(); - Application::getInstance()->handleDialog(dialogMessage); - return false; } - dialogView->showUnknownProgressDialog("Preparing Project", "Maven\nExporting Dependencies"); + if (success) + { + dialogView->showUnknownProgressDialog("Preparing Project", "Maven\nExporting Dependencies"); - utility::mavenCopyDependencies( - mavenPath, projectRootPath, m_settings->getMavenDependenciesDirectoryExpandedAndAbsolute() - ); + success = utility::mavenCopyDependencies( + mavenPath, projectRootPath, m_settings->getMavenDependenciesDirectoryExpandedAndAbsolute() + ); + } + + return success; } return true; diff --git a/src/lib_java/utility/utilityMaven.cpp b/src/lib_java/utility/utilityMaven.cpp index 9370d16c..b3981443 100644 --- a/src/lib_java/utility/utilityMaven.cpp +++ b/src/lib_java/utility/utilityMaven.cpp @@ -66,9 +66,10 @@ namespace utility { setJavaHomeVariableIfNotExists(); - const std::string output = utility::executeProcess( + const std::string output = utility::executeProcessUntilNoOutput( "\"" + mavenPath.str() + "\" generate-sources", - projectDirectoryPath.str() + projectDirectoryPath.str(), + 60000 ); return !output.empty(); } @@ -77,10 +78,26 @@ namespace utility { setJavaHomeVariableIfNotExists(); - const std::string output = utility::executeProcess( + const std::string output = utility::executeProcessUntilNoOutput( "\"" + mavenPath.str() + "\" dependency:copy-dependencies -DoutputDirectory=" + outputDirectoryPath.str(), - projectDirectoryPath.str() + projectDirectoryPath.str(), + 60000 ); + + std::shared_ptr outputAccess = TextAccess::createFromString(output); + for (const std::string& line: outputAccess->getAllLines()) + { + if (utility::isPrefix("[ERROR]", utility::trim(line))) + { + // TODO: move error handling to caller of this function + const std::string dialogMessage = + "The following error occurred while executing a Maven command:\n\n" + utility::replace(line, "\r\n", "\n"); + MessageStatus(dialogMessage, true, false).dispatch(); + Application::getInstance()->handleDialog(dialogMessage); + return false; + } + } + return !output.empty(); } @@ -88,9 +105,10 @@ namespace utility { setJavaHomeVariableIfNotExists(); - std::shared_ptr outputAccess = TextAccess::createFromString(utility::executeProcess( + std::shared_ptr outputAccess = TextAccess::createFromString(utility::executeProcessUntilNoOutput( "\"" + mavenPath.str() + "\" help:effective-pom", - projectDirectoryPath.str() + projectDirectoryPath.str(), + 60000 )); if (outputAccess->getLineCount() > 0 && utility::isPrefix("Error", utility::trim(outputAccess->getLine(1))))