summaryrefslogtreecommitdiffstats
path: root/Source/kwsys/ProcessWin32.c
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2006-05-21 14:27:13 (GMT)
committerBrad King <brad.king@kitware.com>2006-05-21 14:27:13 (GMT)
commit58e8bfb849596fb1b9940f22632d9637b0d7e0c4 (patch)
treed5786d9456ce12c08bdf6a8d5d4118cacf7416eb /Source/kwsys/ProcessWin32.c
parent0d594a453845e083207e6a85797a9b96ec278c75 (diff)
downloadCMake-58e8bfb849596fb1b9940f22632d9637b0d7e0c4.zip
CMake-58e8bfb849596fb1b9940f22632d9637b0d7e0c4.tar.gz
CMake-58e8bfb849596fb1b9940f22632d9637b0d7e0c4.tar.bz2
BUG: Fixed deadlock condition when grandchildren are running after the children exit.
Diffstat (limited to 'Source/kwsys/ProcessWin32.c')
-rw-r--r--Source/kwsys/ProcessWin32.c66
1 files changed, 53 insertions, 13 deletions
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index 97e5706..26b77f9 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -104,6 +104,7 @@ static void kwsysProcessDestroy(kwsysProcess* cp, int event);
static int kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name);
static int kwsysProcessSetupSharedPipe(DWORD nStdHandle, 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 kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
@@ -1145,7 +1146,8 @@ void kwsysProcess_Execute(kwsysProcess* cp)
&si.StartupInfo.hStdError))
{
kwsysProcessCleanup(cp, 1);
- kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
+ kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
+ STD_ERROR_HANDLE);
return;
}
}
@@ -1166,9 +1168,12 @@ void kwsysProcess_Execute(kwsysProcess* cp)
/* Release resources that may have been allocated for this
process before an error occurred. */
kwsysProcessCleanupHandle(&readEnd);
- kwsysProcessCleanupHandle(&si.StartupInfo.hStdInput);
- kwsysProcessCleanupHandle(&si.StartupInfo.hStdOutput);
- kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
+ kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdInput,
+ STD_INPUT_HANDLE);
+ kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdOutput,
+ STD_OUTPUT_HANDLE);
+ kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
+ STD_ERROR_HANDLE);
kwsysProcessCleanupHandle(&si.ErrorPipeRead);
kwsysProcessCleanupHandle(&si.ErrorPipeWrite);
return;
@@ -1183,7 +1188,7 @@ void kwsysProcess_Execute(kwsysProcess* cp)
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. */
- kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
+ kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, STD_ERROR_HANDLE);
/* Restore the working directory. */
if(cp->RealWorkingDirectory)
@@ -1493,7 +1498,7 @@ void kwsysProcess_Kill(kwsysProcess* cp)
/* Make sure we are executing a process. */
if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired ||
- cp->Killed || cp->Terminated)
+ cp->Killed)
{
return;
}
@@ -1501,6 +1506,12 @@ void kwsysProcess_Kill(kwsysProcess* cp)
/* Disable the reading threads. */
kwsysProcessDisablePipeThreads(cp);
+ /* Skip actually killing the child if it has already terminated. */
+ if(cp->Terminated)
+ {
+ return;
+ }
+
/* Kill the children. */
cp->Killed = 1;
if(cp->Win9x)
@@ -1897,8 +1908,10 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
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. */
- kwsysProcessCleanupHandle(&si->StartupInfo.hStdInput);
- kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput);
+ kwsysProcessCleanupHandleSafe(&si->StartupInfo.hStdInput,
+ STD_INPUT_HANDLE);
+ kwsysProcessCleanupHandleSafe(&si->StartupInfo.hStdOutput,
+ STD_OUTPUT_HANDLE);
return 1;
}
@@ -1984,15 +1997,29 @@ int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
/*--------------------------------------------------------------------------*/
int 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. */
kwsysProcessCleanupHandle(handle);
- /* Duplicate the standard handle to be sure it is inherited and can
- be closed later. Do not close the original handle when
+ /* If the standard handle is not inherited then duplicate it to
+ create an inherited copy. Do not close the original handle when
duplicating! */
- if(DuplicateHandle(GetCurrentProcess(), GetStdHandle(nStdHandle),
- GetCurrentProcess(), handle,
- 0, TRUE, DUPLICATE_SAME_ACCESS))
+ if(inherited)
+ {
+ *handle = GetStdHandle(nStdHandle);
+ return 1;
+ }
+ else if(DuplicateHandle(GetCurrentProcess(), GetStdHandle(nStdHandle),
+ GetCurrentProcess(), handle,
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
{
return 1;
}
@@ -2046,6 +2073,19 @@ void kwsysProcessCleanupHandle(PHANDLE h)
/*--------------------------------------------------------------------------*/
+/* 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)))
+ {
+ CloseHandle(*h);
+ *h = 0;
+ }
+}
+
+/*--------------------------------------------------------------------------*/
+
/* Close all handles created by kwsysProcess_Execute. */
void kwsysProcessCleanup(kwsysProcess* cp, int error)
{