diff options
author | Brad King <brad.king@kitware.com> | 2024-11-19 14:02:57 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2024-11-20 11:16:11 (GMT) |
commit | 60af429c5d71d4e159f4f5c129a46482252a924c (patch) | |
tree | ae3d8569591b7d0dd7f59ddd0d3b266d99eaf4f7 | |
parent | d1d20ed397ad46d6959ca6eabe628efae8cc6e10 (diff) | |
download | CMake-60af429c5d71d4e159f4f5c129a46482252a924c.zip CMake-60af429c5d71d4e159f4f5c129a46482252a924c.tar.gz CMake-60af429c5d71d4e159f4f5c129a46482252a924c.tar.bz2 |
execute_process: Restore CLOEXEC on OUTPUT_FILE and ERROR_FILE descriptors
Since commit 5420639a8d (cmExecuteProcessCommand: Replace cmsysProcess
with cmUVProcessChain, 2023-06-01, v3.28.0-rc1~138^2~8), the descriptors
for the `OUTPUT_FILE` and `ERROR_FILE` leak to child processes.
With `ExternalProject` + `INSTALL_COMMAND` + `LOG_INSTALL`, the logging
wrapper script leaks the log files' descriptors to the native build
tool. If they happen to match the `make` job server's pipe fds, e.g.,
with GNU `make` <= 4.3, then the build fails with an error like:
gmake[4]: *** read jobs pipe: Bad file descriptor. Stop.
Fixes: #26398
-rw-r--r-- | Source/cmExecuteProcessCommand.cxx | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 2b923df..9b9ef0b 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -17,6 +17,12 @@ #include <cm3p/uv.h> +#ifndef _WIN32 +# include <fcntl.h> + +# include "cm_fileno.hxx" +#endif + #include "cmArgumentParser.h" #include "cmExecutionStatus.h" #include "cmList.h" @@ -35,6 +41,20 @@ bool cmExecuteProcessCommandIsWhitespace(char c) return (cmIsSpace(c) || c == '\n' || c == '\r'); } +FILE* FopenCLOEXEC(std::string const& path, const char* mode) +{ + FILE* f = cmsys::SystemTools::Fopen(path, mode); +#ifndef _WIN32 + if (f) { + if (fcntl(cm_fileno(f), F_SETFD, FD_CLOEXEC) < 0) { + fclose(f); + f = nullptr; + } + } +#endif + return f; +} + void cmExecuteProcessCommandFixText(std::vector<char>& output, bool strip_trailing_whitespace); void cmExecuteProcessCommandAppend(std::vector<char>& output, const char* data, @@ -178,7 +198,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args, // Check the output variables. std::unique_ptr<FILE, int (*)(FILE*)> inputFile(nullptr, fclose); if (!inputFilename.empty()) { - inputFile.reset(cmsys::SystemTools::Fopen(inputFilename, "rb")); + inputFile.reset(FopenCLOEXEC(inputFilename, "rb")); if (inputFile) { builder.SetExternalStream(cmUVProcessChainBuilder::Stream_INPUT, inputFile.get()); @@ -189,7 +209,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args, std::unique_ptr<FILE, int (*)(FILE*)> outputFile(nullptr, fclose); if (!outputFilename.empty()) { - outputFile.reset(cmsys::SystemTools::Fopen(outputFilename, "wb")); + outputFile.reset(FopenCLOEXEC(outputFilename, "wb")); if (outputFile) { builder.SetExternalStream(cmUVProcessChainBuilder::Stream_OUTPUT, outputFile.get()); @@ -211,7 +231,7 @@ bool cmExecuteProcessCommand(std::vector<std::string> const& args, outputFile.get()); } } else { - errorFile.reset(cmsys::SystemTools::Fopen(errorFilename, "wb")); + errorFile.reset(FopenCLOEXEC(errorFilename, "wb")); if (errorFile) { builder.SetExternalStream(cmUVProcessChainBuilder::Stream_ERROR, errorFile.get()); |