diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CMakeVersion.cmake | 2 | ||||
-rw-r--r-- | Source/cmExecuteProcessCommand.cxx | 24 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudio7Generator.cxx | 18 | ||||
-rw-r--r-- | Source/kwsys/.gitattributes | 16 | ||||
-rw-r--r-- | Source/kwsys/DynamicLoader.cxx | 4 | ||||
-rw-r--r-- | Source/kwsys/Glob.hxx.in | 6 | ||||
-rw-r--r-- | Source/kwsys/Process.h.in | 9 | ||||
-rw-r--r-- | Source/kwsys/ProcessUNIX.c | 360 | ||||
-rw-r--r-- | Source/kwsys/ProcessWin32.c | 564 |
9 files changed, 529 insertions, 474 deletions
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 180cdd7..cf7a523 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 2) -set(CMake_VERSION_PATCH 20150507) +set(CMake_VERSION_PATCH 20150512) #set(CMake_VERSION_RC 1) diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 1225992..a371390 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -255,7 +255,7 @@ bool cmExecuteProcessCommand cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); // Check the output variables. - bool merge_output = (output_variable == error_variable); + bool merge_output = false; if(!input_file.empty()) { cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDIN, input_file.c_str()); @@ -267,8 +267,23 @@ bool cmExecuteProcessCommand } if(!error_file.empty()) { - cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDERR, - error_file.c_str()); + if (error_file == output_file) + { + merge_output = true; + } + else + { + cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDERR, + error_file.c_str()); + } + } + if (!output_variable.empty() && output_variable == error_variable) + { + merge_output = true; + } + if (merge_output) + { + cmsysProcess_SetOption(cp, cmsysProcess_Option_MergeOutput, 1); } // Set the timeout if any. @@ -289,8 +304,7 @@ bool cmExecuteProcessCommand while((p = cmsysProcess_WaitForData(cp, &data, &length, 0), p)) { // Put the output in the right place. - if((p == cmsysProcess_Pipe_STDOUT && !output_quiet) || - (p == cmsysProcess_Pipe_STDERR && !error_quiet && merge_output)) + if (p == cmsysProcess_Pipe_STDOUT && !output_quiet) { if(output_variable.empty()) { diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index de90f7e..ead5ddc 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -1031,6 +1031,24 @@ cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( int type = target->GetType(); if (type == cmTarget::GLOBAL_TARGET) { + // check if INSTALL target is part of default build + if(target->GetName() == "INSTALL") + { + // inspect CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD properties + for(std::vector<std::string>::iterator i = this->Configurations.begin(); + i != this->Configurations.end(); ++i) + { + const char* propertyValue = target->GetMakefile() + ->GetDefinition("CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD"); + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> + cge = ge.Parse(propertyValue); + if(cmSystemTools::IsOn(cge->Evaluate(target->GetMakefile(), *i))) + { + activeConfigs.insert(*i); + } + } + } return activeConfigs; } if(type == cmTarget::UTILITY && !this->IsDependedOn(projectTargets, target)) diff --git a/Source/kwsys/.gitattributes b/Source/kwsys/.gitattributes new file mode 100644 index 0000000..248786e --- /dev/null +++ b/Source/kwsys/.gitattributes @@ -0,0 +1,16 @@ +.git* export-ignore +.gitattributes -export-ignore + +/GitSetup export-ignore +/SetupForDevelopment.sh export-ignore eol=lf + +/CONTRIBUTING.rst conflict-marker-size=78 + +*.c whitespace=tab-in-indent,no-lf-at-eof +*.h whitespace=tab-in-indent,no-lf-at-eof +*.h.in whitespace=tab-in-indent,no-lf-at-eof +*.cxx whitespace=tab-in-indent,no-lf-at-eof +*.hxx whitespace=tab-in-indent,no-lf-at-eof +*.hxx.in whitespace=tab-in-indent,no-lf-at-eof +*.txt whitespace=tab-in-indent,no-lf-at-eof +*.cmake whitespace=tab-in-indent,no-lf-at-eof diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx index 66c7d57..a776f97 100644 --- a/Source/kwsys/DynamicLoader.cxx +++ b/Source/kwsys/DynamicLoader.cxx @@ -48,6 +48,10 @@ DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const kwsys_stl::string& //---------------------------------------------------------------------------- int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) { + if (!lib) + { + return 0; + } return !shl_unload(lib); } diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in index 39b7ce7..5239ccd 100644 --- a/Source/kwsys/Glob.hxx.in +++ b/Source/kwsys/Glob.hxx.in @@ -59,6 +59,12 @@ public: type(msg.type), content(msg.content) {} + Message& operator=(Message const& msg) + { + this->type = msg.type; + this->content = msg.content; + return *this; + } }; typedef kwsys_stl::vector<Message> GlobMessages; diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in index c5995ea..e35939f 100644 --- a/Source/kwsys/Process.h.in +++ b/Source/kwsys/Process.h.in @@ -36,6 +36,7 @@ # define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared) # define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach) # define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow) +# define kwsysProcess_Option_MergeOutput kwsys_ns(Process_Option_MergeOutput) # define kwsysProcess_Option_Verbatim kwsys_ns(Process_Option_Verbatim) # define kwsysProcess_GetOption kwsys_ns(Process_GetOption) # define kwsysProcess_SetOption kwsys_ns(Process_SetOption) @@ -186,6 +187,12 @@ kwsysEXPORT void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, * 0 = No (default) * 1 = Yes * + * kwsysProcess_Option_MergeOutput = Whether to merge stdout/stderr. + * No content will be returned as stderr. + * Any actual stderr will be on stdout. + * 0 = No (default) + * 1 = Yes + * * kwsysProcess_Option_Verbatim = Whether SetCommand and AddCommand * should treat the first argument * as a verbatim command line @@ -200,6 +207,7 @@ enum kwsysProcess_Option_e { kwsysProcess_Option_HideWindow, kwsysProcess_Option_Detach, + kwsysProcess_Option_MergeOutput, kwsysProcess_Option_Verbatim }; @@ -384,6 +392,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp); # undef kwsysProcess_SetPipeShared # undef kwsysProcess_Option_Detach # undef kwsysProcess_Option_HideWindow +# undef kwsysProcess_Option_MergeOutput # undef kwsysProcess_Option_Verbatim # undef kwsysProcess_GetOption # undef kwsysProcess_SetOption diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 1be6d02..0393a6d 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -157,7 +157,7 @@ static void kwsysProcessCleanupDescriptor(int* pfd); static void kwsysProcessClosePipes(kwsysProcess* cp); static int kwsysProcessSetNonBlocking(int fd); static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, - kwsysProcessCreateInformation* si, int* readEnd); + kwsysProcessCreateInformation* si); static void kwsysProcessDestroy(kwsysProcess* cp); static int kwsysProcessSetupOutputPipeFile(int* p, const char* name); static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]); @@ -203,6 +203,10 @@ struct kwsysProcess_s the signal pipe. */ int PipeReadEnds[KWSYSPE_PIPE_COUNT]; + /* Descriptors for the child's ends of the pipes. + Used temporarily during process creation. */ + int PipeChildStd[3]; + /* Write descriptor for child termination signal pipe. */ int SignalPipe; @@ -230,6 +234,9 @@ struct kwsysProcess_s /* Whether to treat command lines as verbatim. */ int Verbatim; + /* Whether to merge stdout/stderr of the child. */ + int MergeOutput; + /* Time at which the child started. Negative for no timeout. */ kwsysProcessTime StartTime; @@ -640,6 +647,7 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) switch(optionId) { case kwsysProcess_Option_Detach: return cp->OptionDetach; + case kwsysProcess_Option_MergeOutput: return cp->MergeOutput; case kwsysProcess_Option_Verbatim: return cp->Verbatim; default: return 0; } @@ -656,6 +664,7 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) switch(optionId) { case kwsysProcess_Option_Detach: cp->OptionDetach = value; break; + case kwsysProcess_Option_MergeOutput: cp->MergeOutput = value; break; case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break; default: break; } @@ -717,7 +726,6 @@ const char* kwsysProcess_GetExceptionString(kwsysProcess* cp) void kwsysProcess_Execute(kwsysProcess* cp) { int i; - kwsysProcessCreateInformation si = {-1, -1, -1, {-1, -1}}; /* Do not execute a second copy simultaneously. */ if(!cp || cp->State == kwsysProcess_State_Executing) @@ -785,7 +793,50 @@ void kwsysProcess_Execute(kwsysProcess* cp) } } - /* Setup the stderr pipe to be shared by all processes. */ + /* Setup the stdin pipe for the first process. */ + if(cp->PipeFileSTDIN) + { + /* Open a file for the child's stdin to read. */ + cp->PipeChildStd[0] = open(cp->PipeFileSTDIN, O_RDONLY); + if(cp->PipeChildStd[0] < 0) + { + kwsysProcessCleanup(cp, 1); + return; + } + + /* Set close-on-exec flag on the pipe's end. */ + if(fcntl(cp->PipeChildStd[0], F_SETFD, FD_CLOEXEC) < 0) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + else if(cp->PipeSharedSTDIN) + { + cp->PipeChildStd[0] = 0; + } + else if(cp->PipeNativeSTDIN[0] >= 0) + { + cp->PipeChildStd[0] = cp->PipeNativeSTDIN[0]; + + /* Set close-on-exec flag on the pipe's ends. The read end will + be dup2-ed into the stdin descriptor after the fork but before + the exec. */ + if((fcntl(cp->PipeNativeSTDIN[0], F_SETFD, FD_CLOEXEC) < 0) || + (fcntl(cp->PipeNativeSTDIN[1], F_SETFD, FD_CLOEXEC) < 0)) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + else + { + cp->PipeChildStd[0] = -1; + } + + /* Create the output pipe for the last process. + We always create this so the pipe can be passed to select even if + it will report closed immediately. */ { /* Create the pipe. */ int p[2]; @@ -796,15 +847,14 @@ void kwsysProcess_Execute(kwsysProcess* cp) } /* Store the pipe. */ - cp->PipeReadEnds[KWSYSPE_PIPE_STDERR] = p[0]; - si.StdErr = p[1]; + cp->PipeReadEnds[KWSYSPE_PIPE_STDOUT] = p[0]; + cp->PipeChildStd[1] = p[1]; /* Set close-on-exec flag on the pipe's ends. */ if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupDescriptor(&si.StdErr); return; } @@ -813,41 +863,93 @@ void kwsysProcess_Execute(kwsysProcess* cp) if(!kwsysProcessSetNonBlocking(p[0])) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupDescriptor(&si.StdErr); return; } } - /* Replace the stderr pipe with a file if requested. In this case - the select call will report that stderr is closed immediately. */ - if(cp->PipeFileSTDERR) + if (cp->PipeFileSTDOUT) { - if(!kwsysProcessSetupOutputPipeFile(&si.StdErr, cp->PipeFileSTDERR)) + /* Use a file for stdout. */ + if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1], + cp->PipeFileSTDOUT)) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + else if (cp->PipeSharedSTDOUT) + { + /* Use the parent stdout. */ + kwsysProcessCleanupDescriptor(&cp->PipeChildStd[1]); + cp->PipeChildStd[1] = 1; + } + else if (cp->PipeNativeSTDOUT[1] >= 0) + { + /* Use the given descriptor for stdout. */ + if(!kwsysProcessSetupOutputPipeNative(&cp->PipeChildStd[1], + cp->PipeNativeSTDOUT)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupDescriptor(&si.StdErr); return; } } - /* Replace the stderr pipe with the parent's if requested. In this - case the select call will report that stderr is closed - immediately. */ - if(cp->PipeSharedSTDERR) + /* Create stderr pipe to be shared by all processes in the pipeline. + We always create this so the pipe can be passed to select even if + it will report closed immediately. */ + { + /* Create the pipe. */ + int p[2]; + if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0) + { + kwsysProcessCleanup(cp, 1); + return; + } + + /* Store the pipe. */ + cp->PipeReadEnds[KWSYSPE_PIPE_STDERR] = p[0]; + cp->PipeChildStd[2] = p[1]; + + /* Set close-on-exec flag on the pipe's ends. */ + if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || + (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) { - kwsysProcessCleanupDescriptor(&si.StdErr); - si.StdErr = 2; + kwsysProcessCleanup(cp, 1); + return; } - /* Replace the stderr pipe with the native pipe provided if any. In - this case the select call will report that stderr is closed - immediately. */ - if(cp->PipeNativeSTDERR[1] >= 0) + /* Set to non-blocking in case select lies, or for the polling + implementation. */ + if(!kwsysProcessSetNonBlocking(p[0])) { - if(!kwsysProcessSetupOutputPipeNative(&si.StdErr, cp->PipeNativeSTDERR)) + kwsysProcessCleanup(cp, 1); + return; + } + } + + if (cp->PipeFileSTDERR) + { + /* Use a file for stderr. */ + if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2], + cp->PipeFileSTDERR)) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + else if (cp->PipeSharedSTDERR) + { + /* Use the parent stderr. */ + kwsysProcessCleanupDescriptor(&cp->PipeChildStd[2]); + cp->PipeChildStd[2] = 2; + } + else if (cp->PipeNativeSTDERR[1] >= 0) + { + /* Use the given handle for stderr. */ + if(!kwsysProcessSetupOutputPipeNative(&cp->PipeChildStd[2], + cp->PipeNativeSTDERR)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupDescriptor(&si.StdErr); return; } } @@ -859,54 +961,85 @@ void kwsysProcess_Execute(kwsysProcess* cp) /* Create the pipeline of processes. */ { - int readEnd = -1; - int failed = 0; + kwsysProcessCreateInformation si = {-1, -1, -1, {-1, -1}}; + int nextStdIn = cp->PipeChildStd[0]; for(i=0; i < cp->NumberOfCommands; ++i) { - if(!kwsysProcessCreate(cp, i, &si, &readEnd)) + /* Setup the process's pipes. */ + si.StdIn = nextStdIn; + if (i == cp->NumberOfCommands-1) { - failed = 1; + nextStdIn = -1; + si.StdOut = cp->PipeChildStd[1]; } - - /* Set the output pipe of the last process to be non-blocking in - case select lies, or for the polling implementation. */ - if(i == (cp->NumberOfCommands-1) && !kwsysProcessSetNonBlocking(readEnd)) - { - failed = 1; - } - - if(failed) + else { - kwsysProcessCleanup(cp, 1); - - /* Release resources that may have been allocated for this - process before an error occurred. */ - kwsysProcessCleanupDescriptor(&readEnd); - if(si.StdIn != 0) - { - kwsysProcessCleanupDescriptor(&si.StdIn); - } - if(si.StdOut != 1) + /* Create a pipe to sit between the children. */ + int p[2] = {-1,-1}; + if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0) { - kwsysProcessCleanupDescriptor(&si.StdOut); + if (nextStdIn != cp->PipeChildStd[0]) + { + kwsysProcessCleanupDescriptor(&nextStdIn); + } + kwsysProcessCleanup(cp, 1); + return; } - if(si.StdErr != 2) + + /* Set close-on-exec flag on the pipe's ends. */ + if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || + (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) { - kwsysProcessCleanupDescriptor(&si.StdErr); + close(p[0]); + close(p[1]); + if (nextStdIn != cp->PipeChildStd[0]) + { + kwsysProcessCleanupDescriptor(&nextStdIn); + } + kwsysProcessCleanup(cp, 1); + return; } + nextStdIn = p[0]; + si.StdOut = p[1]; + } + si.StdErr = cp->MergeOutput? cp->PipeChildStd[1] : cp->PipeChildStd[2]; + + { + int res = kwsysProcessCreate(cp, i, &si); + + /* Close our copies of pipes used between children. */ + if (si.StdIn != cp->PipeChildStd[0]) + { + kwsysProcessCleanupDescriptor(&si.StdIn); + } + if (si.StdOut != cp->PipeChildStd[1]) + { + kwsysProcessCleanupDescriptor(&si.StdOut); + } + if (si.StdErr != cp->PipeChildStd[2] && !cp->MergeOutput) + { + kwsysProcessCleanupDescriptor(&si.StdErr); + } + + if(!res) + { kwsysProcessCleanupDescriptor(&si.ErrorPipe[0]); kwsysProcessCleanupDescriptor(&si.ErrorPipe[1]); + if (nextStdIn != cp->PipeChildStd[0]) + { + kwsysProcessCleanupDescriptor(&nextStdIn); + } + kwsysProcessCleanup(cp, 1); return; } } - /* Save a handle to the output pipe for the last process. */ - cp->PipeReadEnds[KWSYSPE_PIPE_STDOUT] = readEnd; + } } - /* The parent process does not need the output pipe write ends. */ - if(si.StdErr != 2) + /* The parent process does not need the child's pipe ends. */ + for (i=0; i < 3; ++i) { - kwsysProcessCleanupDescriptor(&si.StdErr); + kwsysProcessCleanupDescriptor(&cp->PipeChildStd[i]); } /* Restore the working directory. */ @@ -1414,6 +1547,10 @@ static int kwsysProcessInitialize(kwsysProcess* cp) { cp->PipeReadEnds[i] = -1; } + for(i=0; i < 3; ++i) + { + cp->PipeChildStd[i] = -1; + } cp->SignalPipe = -1; cp->SelectError = 0; cp->StartTime.tv_sec = -1; @@ -1548,13 +1685,17 @@ static void kwsysProcessCleanup(kwsysProcess* cp, int error) { kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); } + for(i=0; i < 3; ++i) + { + kwsysProcessCleanupDescriptor(&cp->PipeChildStd[i]); + } } /*--------------------------------------------------------------------------*/ /* Close the given file descriptor if it is open. Reset its value to -1. */ static void kwsysProcessCleanupDescriptor(int* pfd) { - if(pfd && *pfd >= 0) + if(pfd && *pfd > 2) { /* Keep trying to close until it is not interrupted by a * signal. */ @@ -1615,100 +1756,8 @@ int decc$set_child_standard_streams(int fd1, int fd2, int fd3); /*--------------------------------------------------------------------------*/ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, - kwsysProcessCreateInformation* si, int* readEnd) + kwsysProcessCreateInformation* si) { - /* Setup the process's stdin. */ - if(prIndex > 0) - { - si->StdIn = *readEnd; - *readEnd = 0; - } - else if(cp->PipeFileSTDIN) - { - /* Open a file for the child's stdin to read. */ - si->StdIn = open(cp->PipeFileSTDIN, O_RDONLY); - if(si->StdIn < 0) - { - return 0; - } - - /* Set close-on-exec flag on the pipe's end. */ - if(fcntl(si->StdIn, F_SETFD, FD_CLOEXEC) < 0) - { - return 0; - } - } - else if(cp->PipeSharedSTDIN) - { - si->StdIn = 0; - } - else if(cp->PipeNativeSTDIN[0] >= 0) - { - si->StdIn = cp->PipeNativeSTDIN[0]; - - /* Set close-on-exec flag on the pipe's ends. The read end will - be dup2-ed into the stdin descriptor after the fork but before - the exec. */ - if((fcntl(cp->PipeNativeSTDIN[0], F_SETFD, FD_CLOEXEC) < 0) || - (fcntl(cp->PipeNativeSTDIN[1], F_SETFD, FD_CLOEXEC) < 0)) - { - return 0; - } - } - else - { - si->StdIn = -1; - } - - /* Setup the process's stdout. */ - { - /* Create the pipe. */ - int p[2]; - if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0) - { - return 0; - } - *readEnd = p[0]; - si->StdOut = p[1]; - - /* Set close-on-exec flag on the pipe's ends. */ - if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || - (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) - { - return 0; - } - } - - /* Replace the stdout pipe with a file if requested. In this case - the select call will report that stdout is closed immediately. */ - if(prIndex == cp->NumberOfCommands-1 && cp->PipeFileSTDOUT) - { - if(!kwsysProcessSetupOutputPipeFile(&si->StdOut, cp->PipeFileSTDOUT)) - { - return 0; - } - } - - /* Replace the stdout pipe with the parent's if requested. In this - case the select call will report that stderr is closed - immediately. */ - if(prIndex == cp->NumberOfCommands-1 && cp->PipeSharedSTDOUT) - { - kwsysProcessCleanupDescriptor(&si->StdOut); - si->StdOut = 1; - } - - /* Replace the stdout pipe with the native pipe provided if any. In - this case the select call will report that stdout is closed - immediately. */ - if(prIndex == cp->NumberOfCommands-1 && cp->PipeNativeSTDOUT[1] >= 0) - { - if(!kwsysProcessSetupOutputPipeNative(&si->StdOut, cp->PipeNativeSTDOUT)) - { - return 0; - } - } - /* Create the error reporting pipe. */ if(pipe(si->ErrorPipe) < 0) { @@ -1819,19 +1868,6 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, } } - /* Successfully created this child process. */ - if(prIndex > 0 || si->StdIn > 0) - { - /* The parent process does not need the input pipe read end. */ - kwsysProcessCleanupDescriptor(&si->StdIn); - } - - /* The parent process does not need the output pipe write ends. */ - if(si->StdOut != 1) - { - kwsysProcessCleanupDescriptor(&si->StdOut); - } - return 1; } diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index c2965ea..f630171 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -94,6 +94,11 @@ typedef struct kwsysProcessCreateInformation_s { /* Windows child startup control data. */ STARTUPINFOW StartupInfo; + + /* Original handles before making inherited duplicates. */ + HANDLE hStdInput; + HANDLE hStdOutput; + HANDLE hStdError; } kwsysProcessCreateInformation; @@ -107,15 +112,12 @@ static void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp, kwsysProcessPipeData* td); static int kwsysProcessInitialize(kwsysProcess* cp); static int kwsysProcessCreate(kwsysProcess* cp, int index, - kwsysProcessCreateInformation* si, - PHANDLE readEnd); + kwsysProcessCreateInformation* si); static void kwsysProcessDestroy(kwsysProcess* cp, int event); static int kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name); -static int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle); -static int kwsysProcessSetupPipeNative(PHANDLE handle, HANDLE p[2], - int isWrite); +static void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle); +static void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle); static void kwsysProcessCleanupHandle(PHANDLE h); -static void kwsysProcessCleanupHandleSafe(PHANDLE h, DWORD nStdHandle); static void kwsysProcessCleanup(kwsysProcess* cp, int error); static void kwsysProcessCleanErrorMessage(kwsysProcess* cp); static int kwsysProcessComputeCommandLength(kwsysProcess* cp, @@ -224,6 +226,9 @@ struct kwsysProcess_s /* Whether to treat command lines as verbatim. */ int Verbatim; + /* Whether to merge stdout/stderr of the child. */ + int MergeOutput; + /* Mutex to protect the shared index used by threads to report data. */ HANDLE SharedIndexMutex; @@ -306,6 +311,10 @@ struct kwsysProcess_s /* Real working directory of our own process. */ DWORD RealWorkingDirectoryLength; wchar_t* RealWorkingDirectory; + + /* Own handles for the child's ends of the pipes in the parent process. + Used temporarily during process creation. */ + HANDLE PipeChildStd[3]; }; /*--------------------------------------------------------------------------*/ @@ -446,6 +455,10 @@ kwsysProcess* kwsysProcess_New(void) return 0; } } + for(i=0; i < 3; ++i) + { + cp->PipeChildStd[i] = INVALID_HANDLE_VALUE; + } return cp; } @@ -796,6 +809,7 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) { case kwsysProcess_Option_Detach: return cp->OptionDetach; case kwsysProcess_Option_HideWindow: return cp->HideWindow; + case kwsysProcess_Option_MergeOutput: return cp->MergeOutput; case kwsysProcess_Option_Verbatim: return cp->Verbatim; default: return 0; } @@ -813,6 +827,7 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) { case kwsysProcess_Option_Detach: cp->OptionDetach = value; break; case kwsysProcess_Option_HideWindow: cp->HideWindow = value; break; + case kwsysProcess_Option_MergeOutput: cp->MergeOutput = value; break; case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break; default: break; } @@ -875,9 +890,6 @@ void kwsysProcess_Execute(kwsysProcess* cp) { int i; - /* Child startup control data. */ - kwsysProcessCreateInformation si; - /* Do not execute a second time. */ if(!cp || cp->State == kwsysProcess_State_Executing) { @@ -914,117 +926,211 @@ void kwsysProcess_Execute(kwsysProcess* cp) SetCurrentDirectoryW(cp->WorkingDirectory); } - /* Initialize startup info data. */ - ZeroMemory(&si, sizeof(si)); - si.StartupInfo.cb = sizeof(si.StartupInfo); - - /* Decide whether a child window should be shown. */ - si.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW; - si.StartupInfo.wShowWindow = - (unsigned short)(cp->HideWindow?SW_HIDE:SW_SHOWDEFAULT); - - /* Connect the child's output pipes to the threads. */ - si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; - /* Create stderr pipe to be shared by all processes in the pipeline. - Neither end is directly inherited. */ - if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDERR].Read, - &cp->Pipe[KWSYSPE_PIPE_STDERR].Write, 0, 0)) + /* Setup the stdin pipe for the first process. */ + if(cp->PipeFileSTDIN) { - kwsysProcessCleanup(cp, 1); - return; + /* Create a handle to read a file for stdin. */ + wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN); + cp->PipeChildStd[0] = + CreateFileW(wstdin, GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + 0, OPEN_EXISTING, 0, 0); + free(wstdin); + if(cp->PipeChildStd[0] == INVALID_HANDLE_VALUE) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + else if(cp->PipeSharedSTDIN) + { + /* Share this process's stdin with the child. */ + kwsysProcessSetupSharedPipe(STD_INPUT_HANDLE, &cp->PipeChildStd[0]); + } + else if(cp->PipeNativeSTDIN[0]) + { + /* Use the provided native pipe. */ + kwsysProcessSetupPipeNative(cp->PipeNativeSTDIN[0], &cp->PipeChildStd[0]); + } + else + { + /* Explicitly give the child no stdin. */ + cp->PipeChildStd[0] = INVALID_HANDLE_VALUE; } - /* Create an inherited duplicate of the write end, but do not - close the non-inherited version. We need to keep it open - to use in waking up the pipe threads. */ - if(!DuplicateHandle(GetCurrentProcess(), cp->Pipe[KWSYSPE_PIPE_STDERR].Write, - GetCurrentProcess(), &si.StartupInfo.hStdError, - 0, TRUE, DUPLICATE_SAME_ACCESS)) + /* Create the output pipe for the last process. + We always create this so the pipe thread can run even if we + do not end up giving the write end to the child below. */ + if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDOUT].Read, + &cp->Pipe[KWSYSPE_PIPE_STDOUT].Write, 0, 0)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupHandle(&si.StartupInfo.hStdError); return; } - /* Replace the stderr pipe with a file if requested. In this case - the pipe thread will still run but never report data. */ - if(cp->PipeFileSTDERR) + if(cp->PipeFileSTDOUT) { - if(!kwsysProcessSetupOutputPipeFile(&si.StartupInfo.hStdError, - cp->PipeFileSTDERR)) + /* Use a file for stdout. */ + if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1], + cp->PipeFileSTDOUT)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupHandle(&si.StartupInfo.hStdError); return; } } - - /* Replace the stderr pipe with the parent process's if requested. - In this case the pipe thread will still run but never report - data. */ - if(cp->PipeSharedSTDERR) + else if(cp->PipeSharedSTDOUT) + { + /* Use the parent stdout. */ + kwsysProcessSetupSharedPipe(STD_OUTPUT_HANDLE, &cp->PipeChildStd[1]); + } + else if(cp->PipeNativeSTDOUT[1]) { - if(!kwsysProcessSetupSharedPipe(STD_ERROR_HANDLE, - &si.StartupInfo.hStdError)) + /* Use the given handle for stdout. */ + kwsysProcessSetupPipeNative(cp->PipeNativeSTDOUT[1], &cp->PipeChildStd[1]); + } + else + { + /* Use our pipe for stdout. Duplicate the handle since our waker + thread will use the original. Do not make it inherited yet. */ + if(!DuplicateHandle(GetCurrentProcess(), + cp->Pipe[KWSYSPE_PIPE_STDOUT].Write, + GetCurrentProcess(), &cp->PipeChildStd[1], + 0, FALSE, DUPLICATE_SAME_ACCESS)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, - STD_ERROR_HANDLE); return; } } - /* Replace the stderr pipe with the native pipe provided if any. In - this case the pipe thread will still run but never report - data. */ - if(cp->PipeNativeSTDERR[1]) + /* Create stderr pipe to be shared by all processes in the pipeline. + We always create this so the pipe thread can run even if we do not + end up giving the write end to the child below. */ + if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDERR].Read, + &cp->Pipe[KWSYSPE_PIPE_STDERR].Write, 0, 0)) + { + kwsysProcessCleanup(cp, 1); + return; + } + + if(cp->PipeFileSTDERR) + { + /* Use a file for stderr. */ + if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2], + cp->PipeFileSTDERR)) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + else if(cp->PipeSharedSTDERR) + { + /* Use the parent stderr. */ + kwsysProcessSetupSharedPipe(STD_ERROR_HANDLE, &cp->PipeChildStd[2]); + } + else if(cp->PipeNativeSTDERR[1]) { - if(!kwsysProcessSetupPipeNative(&si.StartupInfo.hStdError, - cp->PipeNativeSTDERR, 1)) + /* Use the given handle for stderr. */ + kwsysProcessSetupPipeNative(cp->PipeNativeSTDERR[1], &cp->PipeChildStd[2]); + } + else + { + /* Use our pipe for stderr. Duplicate the handle since our waker + thread will use the original. Do not make it inherited yet. */ + if(!DuplicateHandle(GetCurrentProcess(), + cp->Pipe[KWSYSPE_PIPE_STDERR].Write, + GetCurrentProcess(), &cp->PipeChildStd[2], + 0, FALSE, DUPLICATE_SAME_ACCESS)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, - STD_ERROR_HANDLE); return; } } /* Create the pipeline of processes. */ { - HANDLE readEnd = 0; + /* Child startup control data. */ + kwsysProcessCreateInformation si; + HANDLE nextStdInput = cp->PipeChildStd[0]; + + /* Initialize startup info data. */ + ZeroMemory(&si, sizeof(si)); + si.StartupInfo.cb = sizeof(si.StartupInfo); + + /* Decide whether a child window should be shown. */ + si.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW; + si.StartupInfo.wShowWindow = + (unsigned short)(cp->HideWindow?SW_HIDE:SW_SHOWDEFAULT); + + /* Connect the child's output pipes to the threads. */ + si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; + for(i=0; i < cp->NumberOfCommands; ++i) { - if(kwsysProcessCreate(cp, i, &si, &readEnd)) + /* Setup the process's pipes. */ + si.hStdInput = nextStdInput; + if (i == cp->NumberOfCommands-1) + { + /* The last child gets the overall stdout. */ + nextStdInput = INVALID_HANDLE_VALUE; + si.hStdOutput = cp->PipeChildStd[1]; + } + else + { + /* Create a pipe to sit between the children. */ + HANDLE p[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; + if (!CreatePipe(&p[0], &p[1], 0, 0)) + { + if (nextStdInput != cp->PipeChildStd[0]) + { + kwsysProcessCleanupHandle(&nextStdInput); + } + kwsysProcessCleanup(cp, 1); + return; + } + nextStdInput = p[0]; + si.hStdOutput = p[1]; + } + si.hStdError = cp->MergeOutput? cp->PipeChildStd[1] : cp->PipeChildStd[2]; + + { + int res = kwsysProcessCreate(cp, i, &si); + + /* Close our copies of pipes used between children. */ + if (si.hStdInput != cp->PipeChildStd[0]) + { + kwsysProcessCleanupHandle(&si.hStdInput); + } + if (si.hStdOutput != cp->PipeChildStd[1]) + { + kwsysProcessCleanupHandle(&si.hStdOutput); + } + if (si.hStdError != cp->PipeChildStd[2] && !cp->MergeOutput) + { + kwsysProcessCleanupHandle(&si.hStdError); + } + if (res) { cp->ProcessEvents[i+1] = cp->ProcessInformation[i].hProcess; } else { + if (nextStdInput != cp->PipeChildStd[0]) + { + kwsysProcessCleanupHandle(&nextStdInput); + } kwsysProcessCleanup(cp, 1); - - /* Release resources that may have been allocated for this - process before an error occurred. */ - kwsysProcessCleanupHandle(&readEnd); - kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdInput, - STD_INPUT_HANDLE); - kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdOutput, - STD_OUTPUT_HANDLE); - kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, - STD_ERROR_HANDLE); return; } } - - /* Save a handle to the output pipe for the last process. */ - cp->Pipe[KWSYSPE_PIPE_STDOUT].Read = readEnd; + } } - /* Close the inherited handles to the stderr pipe shared by all - processes in the pipeline. The stdout and stdin pipes are not - shared among all children and are therefore closed by - kwsysProcessCreate after each child is created. */ - kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, STD_ERROR_HANDLE); + /* The parent process does not need the child's pipe ends. */ + for (i=0; i < 3; ++i) + { + kwsysProcessCleanupHandle(&cp->PipeChildStd[i]); + } /* Restore the working directory. */ if(cp->RealWorkingDirectory) @@ -1543,162 +1649,90 @@ int kwsysProcessInitialize(kwsysProcess* cp) } } } + { + int i; + for (i=0; i < 3; ++i) + { + cp->PipeChildStd[i] = INVALID_HANDLE_VALUE; + } + } return 1; } /*--------------------------------------------------------------------------*/ -int kwsysProcessCreate(kwsysProcess* cp, int index, - kwsysProcessCreateInformation* si, - PHANDLE readEnd) +static int kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn) { - /* Setup the process's stdin. */ - if(*readEnd) - { - /* Create an inherited duplicate of the read end from the output - pipe of the previous process. This also closes the - non-inherited version. */ - if(!DuplicateHandle(GetCurrentProcess(), *readEnd, - GetCurrentProcess(), readEnd, - 0, TRUE, (DUPLICATE_CLOSE_SOURCE | - DUPLICATE_SAME_ACCESS))) - { - return 0; - } - si->StartupInfo.hStdInput = *readEnd; + DWORD flags; - /* This function is done with this handle. */ - *readEnd = 0; - } - else if(cp->PipeFileSTDIN) - { - /* Create a handle to read a file for stdin. */ - wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN); - HANDLE fin = CreateFileW(wstdin, GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_WRITE, - 0, OPEN_EXISTING, 0, 0); - free(wstdin); - if(fin == INVALID_HANDLE_VALUE) - { - return 0; - } - /* Create an inherited duplicate of the handle. This also closes - the non-inherited version. */ - if(!DuplicateHandle(GetCurrentProcess(), fin, - GetCurrentProcess(), &fin, - 0, TRUE, (DUPLICATE_CLOSE_SOURCE | - DUPLICATE_SAME_ACCESS))) - { - return 0; - } - si->StartupInfo.hStdInput = fin; - } - else if(cp->PipeSharedSTDIN) - { - /* Share this process's stdin with the child. */ - if(!kwsysProcessSetupSharedPipe(STD_INPUT_HANDLE, - &si->StartupInfo.hStdInput)) - { - return 0; - } - } - else if(cp->PipeNativeSTDIN[0]) + /* Check whether the handle is valid for this process. */ + if (in != INVALID_HANDLE_VALUE && GetHandleInformation(in, &flags)) { - /* Use the provided native pipe. */ - if(!kwsysProcessSetupPipeNative(&si->StartupInfo.hStdInput, - cp->PipeNativeSTDIN, 0)) + /* Use the handle as-is if it is already inherited. */ + if (flags & HANDLE_FLAG_INHERIT) { - return 0; + *out = in; + return 1; } + + /* Create an inherited copy of this handle. */ + return DuplicateHandle(GetCurrentProcess(), in, + GetCurrentProcess(), out, + 0, TRUE, DUPLICATE_SAME_ACCESS); } else { - /* Explicitly give the child no stdin. */ - si->StartupInfo.hStdInput = INVALID_HANDLE_VALUE; + /* The given handle is not valid for this process. Some child + processes may break if they do not have a valid standard handle, + so open NUL to give to the child. */ + SECURITY_ATTRIBUTES sa; + ZeroMemory(&sa, sizeof(sa)); + sa.nLength = (DWORD)sizeof(sa); + sa.bInheritHandle = 1; + *out = CreateFileW(L"NUL", + (isStdIn ? GENERIC_READ : + (GENERIC_WRITE | FILE_READ_ATTRIBUTES)), + FILE_SHARE_READ|FILE_SHARE_WRITE, + &sa, OPEN_EXISTING, 0, 0); + return *out != INVALID_HANDLE_VALUE; } - /* Setup the process's stdout. */ - { - DWORD maybeClose = DUPLICATE_CLOSE_SOURCE; - HANDLE writeEnd; +} - /* Create the output pipe for this process. Neither end is directly - inherited. */ - if(!CreatePipe(readEnd, &writeEnd, 0, 0)) - { - return 0; - } +/*--------------------------------------------------------------------------*/ +int kwsysProcessCreate(kwsysProcess* cp, int index, + kwsysProcessCreateInformation* si) +{ + int res = - /* Create an inherited duplicate of the write end. Close the - non-inherited version unless this is the last process. Save the - non-inherited write end of the last process. */ - if(index == cp->NumberOfCommands-1) - { - cp->Pipe[KWSYSPE_PIPE_STDOUT].Write = writeEnd; - maybeClose = 0; - } - if(!DuplicateHandle(GetCurrentProcess(), writeEnd, - GetCurrentProcess(), &writeEnd, - 0, TRUE, (maybeClose | DUPLICATE_SAME_ACCESS))) - { - return 0; - } - si->StartupInfo.hStdOutput = writeEnd; - } + /* Create inherited copies the handles. */ + kwsysProcessCreateChildHandle(&si->StartupInfo.hStdInput, + si->hStdInput, 1) && + kwsysProcessCreateChildHandle(&si->StartupInfo.hStdOutput, + si->hStdOutput, 0) && + kwsysProcessCreateChildHandle(&si->StartupInfo.hStdError, + si->hStdError, 0) && - /* Replace the stdout pipe with a file if requested. In this case - the pipe thread will still run but never report data. */ - if(index == cp->NumberOfCommands-1 && cp->PipeFileSTDOUT) - { - if(!kwsysProcessSetupOutputPipeFile(&si->StartupInfo.hStdOutput, - cp->PipeFileSTDOUT)) - { - return 0; - } - } + /* Create the child in a suspended state so we can wait until all + children have been created before running any one. */ + CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0, + 0, &si->StartupInfo, &cp->ProcessInformation[index]); - /* Replace the stdout pipe of the last child with the parent - process's if requested. In this case the pipe thread will still - run but never report data. */ - if(index == cp->NumberOfCommands-1 && cp->PipeSharedSTDOUT) + /* Close the inherited copies of the handles. */ + if (si->StartupInfo.hStdInput != si->hStdInput) { - if(!kwsysProcessSetupSharedPipe(STD_OUTPUT_HANDLE, - &si->StartupInfo.hStdOutput)) - { - return 0; - } + kwsysProcessCleanupHandle(&si->StartupInfo.hStdInput); } - - /* Replace the stdout pipe with the native pipe provided if any. In - this case the pipe thread will still run but never report - data. */ - if(index == cp->NumberOfCommands-1 && cp->PipeNativeSTDOUT[1]) + if (si->StartupInfo.hStdOutput != si->hStdOutput) { - if(!kwsysProcessSetupPipeNative(&si->StartupInfo.hStdOutput, - cp->PipeNativeSTDOUT, 1)) - { - return 0; - } + kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput); } - - /* Create the child in a suspended state so we can wait until all - children have been created before running any one. */ - if(!CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0, - 0, &si->StartupInfo, &cp->ProcessInformation[index])) + if (si->StartupInfo.hStdError != si->hStdError) { - return 0; + kwsysProcessCleanupHandle(&si->StartupInfo.hStdError); } - /* Successfully created this child process. Close the current - process's copies of the inherited stdout and stdin handles. The - stderr handle is shared among all children and is closed by - kwsysProcess_Execute after all children have been created. */ - kwsysProcessCleanupHandleSafe(&si->StartupInfo.hStdInput, - STD_INPUT_HANDLE); - kwsysProcessCleanupHandleSafe(&si->StartupInfo.hStdOutput, - STD_OUTPUT_HANDLE); - - return 1; + return res; } /*--------------------------------------------------------------------------*/ @@ -1763,7 +1797,7 @@ int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) return 1; } - /* Close the existing inherited handle. */ + /* Close the existing handle. */ kwsysProcessCleanupHandle(phandle); /* Create a handle to write a file for the pipe. */ @@ -1776,103 +1810,27 @@ int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) return 0; } - /* Create an inherited duplicate of the handle. This also closes - the non-inherited version. */ - if(!DuplicateHandle(GetCurrentProcess(), fout, - GetCurrentProcess(), &fout, - 0, TRUE, (DUPLICATE_CLOSE_SOURCE | - DUPLICATE_SAME_ACCESS))) - { - return 0; - } - /* Assign the replacement handle. */ *phandle = fout; return 1; } /*--------------------------------------------------------------------------*/ -int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle) +void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle) { - /* Check whether the handle to be shared is already inherited. */ - DWORD flags; - int inherited = 0; - if(GetHandleInformation(GetStdHandle(nStdHandle), &flags) && - (flags & HANDLE_FLAG_INHERIT)) - { - inherited = 1; - } - - /* Cleanup the previous handle. */ + /* Close the existing handle. */ kwsysProcessCleanupHandle(handle); - - /* If the standard handle is not inherited then duplicate it to - create an inherited copy. Do not close the original handle when - duplicating! */ - if(inherited) - { - *handle = GetStdHandle(nStdHandle); - return 1; - } - else if(DuplicateHandle(GetCurrentProcess(), GetStdHandle(nStdHandle), - GetCurrentProcess(), handle, - 0, TRUE, DUPLICATE_SAME_ACCESS)) - { - return 1; - } - else - { - /* The given standard handle is not valid for this process. Some - child processes may break if they do not have a valid standard - pipe, so give the child an empty pipe. For the stdin pipe we - want to close the write end and give the read end to the child. - For stdout and stderr we want to close the read end and give - the write end to the child. */ - int child_end = (nStdHandle == STD_INPUT_HANDLE)? 0:1; - int parent_end = (nStdHandle == STD_INPUT_HANDLE)? 1:0; - HANDLE emptyPipe[2]; - if(!CreatePipe(&emptyPipe[0], &emptyPipe[1], 0, 0)) - { - return 0; - } - - /* Close the non-inherited end so the pipe will be broken - immediately. */ - CloseHandle(emptyPipe[parent_end]); - - /* Create an inherited duplicate of the handle. This also - closes the non-inherited version. */ - if(!DuplicateHandle(GetCurrentProcess(), emptyPipe[child_end], - GetCurrentProcess(), &emptyPipe[child_end], - 0, TRUE, (DUPLICATE_CLOSE_SOURCE | - DUPLICATE_SAME_ACCESS))) - { - return 0; - } - - /* Give the inherited handle to the child. */ - *handle = emptyPipe[child_end]; - return 1; - } + /* Store the new standard handle. */ + *handle = GetStdHandle(nStdHandle); } /*--------------------------------------------------------------------------*/ -int kwsysProcessSetupPipeNative(PHANDLE handle, HANDLE p[2], int isWrite) +void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle) { - /* Close the existing inherited handle. */ + /* Close the existing handle. */ kwsysProcessCleanupHandle(handle); - - /* Create an inherited duplicate of the handle. This also closes - the non-inherited version. */ - if(!DuplicateHandle(GetCurrentProcess(), p[isWrite? 1:0], - GetCurrentProcess(), handle, - 0, TRUE, (DUPLICATE_CLOSE_SOURCE | - DUPLICATE_SAME_ACCESS))) - { - return 0; - } - - return 1; + /* Store the new given handle. */ + *handle = native; } /*--------------------------------------------------------------------------*/ @@ -1880,23 +1838,13 @@ int kwsysProcessSetupPipeNative(PHANDLE handle, HANDLE p[2], int isWrite) /* Close the given handle if it is open. Reset its value to 0. */ void kwsysProcessCleanupHandle(PHANDLE h) { - if(h && *h) - { - CloseHandle(*h); - *h = 0; - } -} - -/*--------------------------------------------------------------------------*/ - -/* Close the given handle if it is open and not a standard handle. - Reset its value to 0. */ -void kwsysProcessCleanupHandleSafe(PHANDLE h, DWORD nStdHandle) -{ - if(h && *h && (*h != GetStdHandle(nStdHandle))) + if(h && *h && *h != INVALID_HANDLE_VALUE && + *h != GetStdHandle(STD_INPUT_HANDLE) && + *h != GetStdHandle(STD_OUTPUT_HANDLE) && + *h != GetStdHandle(STD_ERROR_HANDLE)) { CloseHandle(*h); - *h = 0; + *h = INVALID_HANDLE_VALUE; } } @@ -1986,6 +1934,10 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error) kwsysProcessCleanupHandle(&cp->Pipe[i].Read); cp->Pipe[i].Closed = 0; } + for(i=0; i < 3; ++i) + { + kwsysProcessCleanupHandle(&cp->PipeChildStd[i]); + } } /*--------------------------------------------------------------------------*/ |