BUG: Fixed deadlock condition when grandchildren are running after the children exit.

This commit is contained in:
Brad King 2006-05-21 10:27:13 -04:00
parent 0d594a4538
commit 58e8bfb849
1 changed files with 53 additions and 13 deletions

View File

@ -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)
{