diff options
author | Brad King <brad.king@kitware.com> | 2020-12-14 12:07:39 (GMT) |
---|---|---|
committer | Kitware Robot <kwrobot@kitware.com> | 2020-12-14 12:07:46 (GMT) |
commit | 922ad5c6b9ea98d77c85c1378f088f7b20bdc6bf (patch) | |
tree | 7741c48e6db3667b1374d3713db13d8d9e96cbc4 | |
parent | 0a6c7cdd07565e6a50ef69d4f2595ace238fa408 (diff) | |
parent | e5a4ffaad166de7a8b907919ca2d805a3ec72c39 (diff) | |
download | CMake-922ad5c6b9ea98d77c85c1378f088f7b20bdc6bf.zip CMake-922ad5c6b9ea98d77c85c1378f088f7b20bdc6bf.tar.gz CMake-922ad5c6b9ea98d77c85c1378f088f7b20bdc6bf.tar.bz2 |
Merge topic 'execute_process-command-error'
e5a4ffaad1 execute_process: Improve COMMAND_ERROR_IS_FATAL error capture scenarios
Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !5588
22 files changed, 217 insertions, 42 deletions
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 14147e0..5a85b7d 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -6,8 +6,10 @@ #include <cctype> /* isspace */ #include <cstdio> #include <iostream> +#include <map> #include <memory> #include <sstream> +#include <utility> #include <vector> #include <cm/string_view> @@ -375,47 +377,101 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args, } } - if (arguments.CommandErrorIsFatal == "ANY"_s) { - if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) { - std::vector<int> failedIndexes; - for (int i = 0; i < static_cast<int>(arguments.Commands.size()); ++i) { - if (cmsysProcess_GetStateByIndex(cp, i) == - kwsysProcess_StateByIndex_Exited) { - int exitCode = cmsysProcess_GetExitValueByIndex(cp, i); - if (exitCode) { - failedIndexes.push_back(i); - } + auto queryProcessStatusByIndex = [&cp](int index) -> std::string { + std::string processStatus; + switch (cmsysProcess_GetStateByIndex(cp, static_cast<int>(index))) { + case kwsysProcess_StateByIndex_Exited: { + int exitCode = cmsysProcess_GetExitValueByIndex(cp, index); + if (exitCode) { + processStatus = "Child return code: " + std::to_string(exitCode); } + } break; + case kwsysProcess_StateByIndex_Exception: { + processStatus = cmStrCat( + "Abnormal exit with child return code: ", + cmsysProcess_GetExceptionStringByIndex(cp, static_cast<int>(index))); + break; } - if (!failedIndexes.empty()) { - std::ostringstream oss; - oss << "failed command indexes: "; - for (auto i = 0u; i < failedIndexes.size(); i++) { - if (i == failedIndexes.size() - 1) { - oss << failedIndexes[i] + 1; - } else { - oss << failedIndexes[i] + 1 << ", "; + case kwsysProcess_StateByIndex_Error: + default: + processStatus = "Error getting the child return code"; + break; + } + return processStatus; + }; + + if (arguments.CommandErrorIsFatal == "ANY"_s) { + bool ret = true; + switch (cmsysProcess_GetState(cp)) { + case cmsysProcess_State_Exited: { + std::map<int, std::string> failureIndices; + for (int i = 0; i < static_cast<int>(arguments.Commands.size()); ++i) { + std::string processStatus = queryProcessStatusByIndex(i); + if (!processStatus.empty()) { + failureIndices[i] = processStatus; + } + if (!failureIndices.empty()) { + std::ostringstream oss; + oss << "failed command indexes:\n"; + for (auto const& e : failureIndices) { + oss << " " << e.first + 1 << ": \"" << e.second << "\"\n"; + } + status.SetError(oss.str()); + ret = false; } } - status.SetError(oss.str()); - cmSystemTools::SetFatalErrorOccured(); - return false; - } + } break; + case cmsysProcess_State_Exception: + status.SetError( + cmStrCat("abnormal exit: ", cmsysProcess_GetExceptionString(cp))); + ret = false; + break; + case cmsysProcess_State_Error: + status.SetError(cmStrCat("error getting child return code: ", + cmsysProcess_GetErrorString(cp))); + ret = false; + break; + case cmsysProcess_State_Expired: + status.SetError("Process terminated due to timeout"); + ret = false; + break; + } + + if (!ret) { + cmSystemTools::SetFatalErrorOccured(); + return false; } } if (arguments.CommandErrorIsFatal == "LAST"_s) { - if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) { - int lastIndex = static_cast<int>(arguments.Commands.size() - 1); - if (cmsysProcess_GetStateByIndex(cp, lastIndex) == - kwsysProcess_StateByIndex_Exited) { - int exitCode = cmsysProcess_GetExitValueByIndex(cp, lastIndex); - if (exitCode) { + bool ret = true; + switch (cmsysProcess_GetState(cp)) { + case cmsysProcess_State_Exited: { + int lastIndex = static_cast<int>(arguments.Commands.size() - 1); + const std::string processStatus = queryProcessStatusByIndex(lastIndex); + if (!processStatus.empty()) { status.SetError("last command failed"); - cmSystemTools::SetFatalErrorOccured(); - return false; + ret = false; } - } + } break; + case cmsysProcess_State_Exception: + status.SetError( + cmStrCat("Abnormal exit: ", cmsysProcess_GetExceptionString(cp))); + ret = false; + break; + case cmsysProcess_State_Error: + status.SetError(cmStrCat("Error getting child return code: ", + cmsysProcess_GetErrorString(cp))); + ret = false; + break; + case cmsysProcess_State_Expired: + status.SetError("Process terminated due to timeout"); + ret = false; + break; + } + if (!ret) { + cmSystemTools::SetFatalErrorOccured(); + return false; } } diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index 0cab867..c0e4bce 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -316,7 +316,10 @@ add_RunCMake_test(add_subdirectory) add_RunCMake_test(add_test) add_RunCMake_test(build_command) add_executable(exit_code exit_code.c) -set(execute_process_ARGS -DEXIT_CODE_EXE=$<TARGET_FILE:exit_code>) +set(execute_process_ARGS + -DEXIT_CODE_EXE=$<TARGET_FILE:exit_code> + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + ) if(NOT CMake_TEST_EXTERNAL_CMAKE) list(APPEND execute_process_ARGS -DTEST_ENCODING_EXE=$<TARGET_FILE:testEncoding>) endif() diff --git a/Tests/RunCMake/execute_process/AnyCommandAbnormalExit-result.txt b/Tests/RunCMake/execute_process/AnyCommandAbnormalExit-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/execute_process/AnyCommandAbnormalExit-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/execute_process/AnyCommandAbnormalExit-stderr.txt b/Tests/RunCMake/execute_process/AnyCommandAbnormalExit-stderr.txt new file mode 100644 index 0000000..9627872 --- /dev/null +++ b/Tests/RunCMake/execute_process/AnyCommandAbnormalExit-stderr.txt @@ -0,0 +1,4 @@ +CMake Error at .*AnyCommandAbnormalExit.cmake:[0-9]+ \(execute_process\): + execute_process failed command indexes: + + 1: "Abnormal exit with child return code: Segmentation fault diff --git a/Tests/RunCMake/execute_process/AnyCommandAbnormalExit.cmake b/Tests/RunCMake/execute_process/AnyCommandAbnormalExit.cmake new file mode 100644 index 0000000..5ac0c21 --- /dev/null +++ b/Tests/RunCMake/execute_process/AnyCommandAbnormalExit.cmake @@ -0,0 +1,5 @@ +execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c + "import os; os.kill(os.getpid(),11)" + COMMAND ${CMAKE_COMMAND} -E true + COMMAND_ERROR_IS_FATAL ANY + ) diff --git a/Tests/RunCMake/execute_process/AnyCommandError-stderr.txt b/Tests/RunCMake/execute_process/AnyCommandError-stderr.txt index 0380562..bf36391 100644 --- a/Tests/RunCMake/execute_process/AnyCommandError-stderr.txt +++ b/Tests/RunCMake/execute_process/AnyCommandError-stderr.txt @@ -1,2 +1,5 @@ CMake Error at .*AnyCommandError.cmake:1 \(execute_process\): - execute_process failed command indexes: 2, 3, 4 + execute_process failed command indexes: + + 2: "Child return code: 1" + 3: "Child return code: 1" diff --git a/Tests/RunCMake/execute_process/AnyCommandError.cmake b/Tests/RunCMake/execute_process/AnyCommandError.cmake index f8ec385..c9348cd 100644 --- a/Tests/RunCMake/execute_process/AnyCommandError.cmake +++ b/Tests/RunCMake/execute_process/AnyCommandError.cmake @@ -1,8 +1,6 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E true - COMMAND ${CMAKE_COMMAND} -E false - COMMAND ${CMAKE_COMMAND} -E false - COMMAND ${CMAKE_COMMAND} -E false - COMMAND ${CMAKE_COMMAND} -E true - COMMAND ${CMAKE_COMMAND} -E true - COMMAND_ERROR_IS_FATAL ANY + COMMAND ${CMAKE_COMMAND} -E false + COMMAND ${CMAKE_COMMAND} -E false + COMMAND ${CMAKE_COMMAND} -E true + COMMAND_ERROR_IS_FATAL ANY ) diff --git a/Tests/RunCMake/execute_process/AnyCommandGood.cmake b/Tests/RunCMake/execute_process/AnyCommandGood.cmake new file mode 100644 index 0000000..27f0996 --- /dev/null +++ b/Tests/RunCMake/execute_process/AnyCommandGood.cmake @@ -0,0 +1,4 @@ +execute_process(COMMAND ${CMAKE_COMMAND} -E true + COMMAND ${CMAKE_COMMAND} -E true + COMMAND_ERROR_IS_FATAL ANY + ) diff --git a/Tests/RunCMake/execute_process/AnyCommandTimeout-result.txt b/Tests/RunCMake/execute_process/AnyCommandTimeout-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/execute_process/AnyCommandTimeout-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/execute_process/AnyCommandTimeout-stderr.txt b/Tests/RunCMake/execute_process/AnyCommandTimeout-stderr.txt new file mode 100644 index 0000000..10cc5f4 --- /dev/null +++ b/Tests/RunCMake/execute_process/AnyCommandTimeout-stderr.txt @@ -0,0 +1,2 @@ +CMake Error at .*AnyCommandTimeout.cmake:9 \(execute_process\): + execute_process Process terminated due to timeout diff --git a/Tests/RunCMake/execute_process/AnyCommandTimeout.cmake b/Tests/RunCMake/execute_process/AnyCommandTimeout.cmake new file mode 100644 index 0000000..a5a53fd --- /dev/null +++ b/Tests/RunCMake/execute_process/AnyCommandTimeout.cmake @@ -0,0 +1,15 @@ +execute_process(COMMAND ${CMAKE_COMMAND} -E true + COMMAND ${CMAKE_COMMAND} -E sleep 10 + COMMAND ${CMAKE_COMMAND} -E true + TIMEOUT 1 + RESULT_VARIABLE result +) + +if(NOT result EQUAL "0") + execute_process(COMMAND ${CMAKE_COMMAND} -E true + COMMAND ${CMAKE_COMMAND} -E sleep 10 + COMMAND ${CMAKE_COMMAND} -E true + TIMEOUT 1 + COMMAND_ERROR_IS_FATAL ANY + ) +endif() diff --git a/Tests/RunCMake/execute_process/LastCommandAbnormalExit-1.cmake b/Tests/RunCMake/execute_process/LastCommandAbnormalExit-1.cmake new file mode 100644 index 0000000..5a4574c --- /dev/null +++ b/Tests/RunCMake/execute_process/LastCommandAbnormalExit-1.cmake @@ -0,0 +1,13 @@ +execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c + "import os; os.kill(os.getpid(),11)" + COMMAND ${CMAKE_COMMAND} -E true + RESULT_VARIABLE result + ) + +if(result EQUAL "0") + execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c + "import os; os.kill(os.getpid(),11)" + COMMAND ${CMAKE_COMMAND} -E true + COMMAND_ERROR_IS_FATAL LAST + ) +endif() diff --git a/Tests/RunCMake/execute_process/LastCommandAbnormalExit-2-result.txt b/Tests/RunCMake/execute_process/LastCommandAbnormalExit-2-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/execute_process/LastCommandAbnormalExit-2-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/execute_process/LastCommandAbnormalExit-2-stderr.txt b/Tests/RunCMake/execute_process/LastCommandAbnormalExit-2-stderr.txt new file mode 100644 index 0000000..c915e58 --- /dev/null +++ b/Tests/RunCMake/execute_process/LastCommandAbnormalExit-2-stderr.txt @@ -0,0 +1,2 @@ +CMake Error at .*LastCommandAbnormalExit-2.cmake:[0-9]+ \(execute_process\): + execute_process Abnormal exit: Segmentation fault diff --git a/Tests/RunCMake/execute_process/LastCommandAbnormalExit-2.cmake b/Tests/RunCMake/execute_process/LastCommandAbnormalExit-2.cmake new file mode 100644 index 0000000..b87e0f7 --- /dev/null +++ b/Tests/RunCMake/execute_process/LastCommandAbnormalExit-2.cmake @@ -0,0 +1,13 @@ +execute_process(COMMAND ${CMAKE_COMMAND} -E true + COMMAND "${PYTHON_EXECUTABLE}" -c + "import os; os.kill(os.getpid(),11)" + RESULT_VARIABLE result + ) + +if(NOT result EQUAL "0") + execute_process(COMMAND ${CMAKE_COMMAND} -E true + COMMAND "${PYTHON_EXECUTABLE}" -c + "import os; os.kill(os.getpid(),11)" + COMMAND_ERROR_IS_FATAL LAST + ) +endif() diff --git a/Tests/RunCMake/execute_process/LastCommandError-stderr.txt b/Tests/RunCMake/execute_process/LastCommandError-stderr.txt index ff191b3..335a771 100644 --- a/Tests/RunCMake/execute_process/LastCommandError-stderr.txt +++ b/Tests/RunCMake/execute_process/LastCommandError-stderr.txt @@ -1,2 +1,2 @@ -CMake Error at .*LastCommandError.cmake:1 \(execute_process\): +CMake Error at .*LastCommandError.cmake:11 \(execute_process\): execute_process last command failed diff --git a/Tests/RunCMake/execute_process/LastCommandError.cmake b/Tests/RunCMake/execute_process/LastCommandError.cmake index 6116a5c..9a925fe 100644 --- a/Tests/RunCMake/execute_process/LastCommandError.cmake +++ b/Tests/RunCMake/execute_process/LastCommandError.cmake @@ -1,8 +1,19 @@ execute_process(COMMAND ${CMAKE_COMMAND} -E true + COMMAND ${CMAKE_COMMAND} -E false + COMMAND ${CMAKE_COMMAND} -E false + COMMAND ${CMAKE_COMMAND} -E false + COMMAND ${CMAKE_COMMAND} -E true + COMMAND ${CMAKE_COMMAND} -E false + RESULT_VARIABLE result +) + +if(NOT result EQUAL "0") + execute_process(COMMAND ${CMAKE_COMMAND} -E true COMMAND ${CMAKE_COMMAND} -E false COMMAND ${CMAKE_COMMAND} -E false COMMAND ${CMAKE_COMMAND} -E false COMMAND ${CMAKE_COMMAND} -E true COMMAND ${CMAKE_COMMAND} -E false COMMAND_ERROR_IS_FATAL LAST -) + ) +endif() diff --git a/Tests/RunCMake/execute_process/LastCommandGood.cmake b/Tests/RunCMake/execute_process/LastCommandGood.cmake new file mode 100644 index 0000000..c22b49d --- /dev/null +++ b/Tests/RunCMake/execute_process/LastCommandGood.cmake @@ -0,0 +1,15 @@ +execute_process(COMMAND ${CMAKE_COMMAND} -E true + COMMAND ${CMAKE_COMMAND} -E false + COMMAND ${CMAKE_COMMAND} -E false + COMMAND ${CMAKE_COMMAND} -E true + RESULT_VARIABLE result + ) + +if(result EQUAL "0") + execute_process(COMMAND ${CMAKE_COMMAND} -E true + COMMAND ${CMAKE_COMMAND} -E false + COMMAND ${CMAKE_COMMAND} -E false + COMMAND ${CMAKE_COMMAND} -E true + COMMAND_ERROR_IS_FATAL LAST + ) +endif() diff --git a/Tests/RunCMake/execute_process/LastCommandTimeout-result.txt b/Tests/RunCMake/execute_process/LastCommandTimeout-result.txt new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/Tests/RunCMake/execute_process/LastCommandTimeout-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/execute_process/LastCommandTimeout-stderr.txt b/Tests/RunCMake/execute_process/LastCommandTimeout-stderr.txt new file mode 100644 index 0000000..1cd1546 --- /dev/null +++ b/Tests/RunCMake/execute_process/LastCommandTimeout-stderr.txt @@ -0,0 +1,2 @@ +CMake Error at .*LastCommandTimeout.cmake:9 \(execute_process\): + execute_process Process terminated due to timeout diff --git a/Tests/RunCMake/execute_process/LastCommandTimeout.cmake b/Tests/RunCMake/execute_process/LastCommandTimeout.cmake new file mode 100644 index 0000000..9c1f444 --- /dev/null +++ b/Tests/RunCMake/execute_process/LastCommandTimeout.cmake @@ -0,0 +1,15 @@ +execute_process(COMMAND ${CMAKE_COMMAND} -E true + COMMAND ${CMAKE_COMMAND} -E sleep 10 + COMMAND ${CMAKE_COMMAND} -E true + TIMEOUT 1 + RESULT_VARIABLE result +) + +if(NOT result EQUAL "0") + execute_process(COMMAND ${CMAKE_COMMAND} -E true + COMMAND ${CMAKE_COMMAND} -E sleep 10 + COMMAND ${CMAKE_COMMAND} -E true + TIMEOUT 1 + COMMAND_ERROR_IS_FATAL LAST + ) +endif() diff --git a/Tests/RunCMake/execute_process/RunCMakeTest.cmake b/Tests/RunCMake/execute_process/RunCMakeTest.cmake index f4c3d19..35712f6 100644 --- a/Tests/RunCMake/execute_process/RunCMakeTest.cmake +++ b/Tests/RunCMake/execute_process/RunCMakeTest.cmake @@ -27,6 +27,16 @@ run_cmake_command(EchoCommand3 ${CMAKE_COMMAND} run_cmake_command(EchoVariable ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/EchoVariable.cmake) +run_cmake_command(CommandError ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/CommandError.cmake) run_cmake_command(AnyCommandError ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/AnyCommandError.cmake) +run_cmake_command(AnyCommandTimeout ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/AnyCommandTimeout.cmake) +run_cmake_command(AnyCommandGood ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/AnyCommandGood.cmake) run_cmake_command(LastCommandError ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/LastCommandError.cmake) -run_cmake_command(CommandError ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/CommandError.cmake) +run_cmake_command(LastCommandTimeout ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/LastCommandTimeout.cmake) +run_cmake_command(LastCommandGood ${CMAKE_COMMAND} -P ${RunCMake_SOURCE_DIR}/LastCommandGood.cmake) + +if(UNIX AND PYTHON_EXECUTABLE) + run_cmake_command(AnyCommandAbnormalExit ${CMAKE_COMMAND} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} -P ${RunCMake_SOURCE_DIR}/AnyCommandAbnormalExit.cmake) + run_cmake_command(LastCommandAbnormalExit-1 ${CMAKE_COMMAND} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} -P ${RunCMake_SOURCE_DIR}/LastCommandAbnormalExit-1.cmake) + run_cmake_command(LastCommandAbnormalExit-2 ${CMAKE_COMMAND} -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} -P ${RunCMake_SOURCE_DIR}/LastCommandAbnormalExit-2.cmake) +endif() |