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 kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name);
static int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle); static int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle);
static void kwsysProcessCleanupHandle(PHANDLE h); static void kwsysProcessCleanupHandle(PHANDLE h);
static void kwsysProcessCleanupHandleSafe(PHANDLE h, DWORD nStdHandle);
static void kwsysProcessCleanup(kwsysProcess* cp, int error); static void kwsysProcessCleanup(kwsysProcess* cp, int error);
static void kwsysProcessCleanErrorMessage(kwsysProcess* cp); static void kwsysProcessCleanErrorMessage(kwsysProcess* cp);
static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
@ -1145,7 +1146,8 @@ void kwsysProcess_Execute(kwsysProcess* cp)
&si.StartupInfo.hStdError)) &si.StartupInfo.hStdError))
{ {
kwsysProcessCleanup(cp, 1); kwsysProcessCleanup(cp, 1);
kwsysProcessCleanupHandle(&si.StartupInfo.hStdError); kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
STD_ERROR_HANDLE);
return; return;
} }
} }
@ -1166,9 +1168,12 @@ void kwsysProcess_Execute(kwsysProcess* cp)
/* Release resources that may have been allocated for this /* Release resources that may have been allocated for this
process before an error occurred. */ process before an error occurred. */
kwsysProcessCleanupHandle(&readEnd); kwsysProcessCleanupHandle(&readEnd);
kwsysProcessCleanupHandle(&si.StartupInfo.hStdInput); kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdInput,
kwsysProcessCleanupHandle(&si.StartupInfo.hStdOutput); STD_INPUT_HANDLE);
kwsysProcessCleanupHandle(&si.StartupInfo.hStdError); kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdOutput,
STD_OUTPUT_HANDLE);
kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError,
STD_ERROR_HANDLE);
kwsysProcessCleanupHandle(&si.ErrorPipeRead); kwsysProcessCleanupHandle(&si.ErrorPipeRead);
kwsysProcessCleanupHandle(&si.ErrorPipeWrite); kwsysProcessCleanupHandle(&si.ErrorPipeWrite);
return; return;
@ -1183,7 +1188,7 @@ void kwsysProcess_Execute(kwsysProcess* cp)
processes in the pipeline. The stdout and stdin pipes are not processes in the pipeline. The stdout and stdin pipes are not
shared among all children and are therefore closed by shared among all children and are therefore closed by
kwsysProcessCreate after each child is created. */ kwsysProcessCreate after each child is created. */
kwsysProcessCleanupHandle(&si.StartupInfo.hStdError); kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, STD_ERROR_HANDLE);
/* Restore the working directory. */ /* Restore the working directory. */
if(cp->RealWorkingDirectory) if(cp->RealWorkingDirectory)
@ -1493,7 +1498,7 @@ void kwsysProcess_Kill(kwsysProcess* cp)
/* Make sure we are executing a process. */ /* Make sure we are executing a process. */
if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired || if(!cp || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired ||
cp->Killed || cp->Terminated) cp->Killed)
{ {
return; return;
} }
@ -1501,6 +1506,12 @@ void kwsysProcess_Kill(kwsysProcess* cp)
/* Disable the reading threads. */ /* Disable the reading threads. */
kwsysProcessDisablePipeThreads(cp); kwsysProcessDisablePipeThreads(cp);
/* Skip actually killing the child if it has already terminated. */
if(cp->Terminated)
{
return;
}
/* Kill the children. */ /* Kill the children. */
cp->Killed = 1; cp->Killed = 1;
if(cp->Win9x) if(cp->Win9x)
@ -1897,8 +1908,10 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
process's copies of the inherited stdout and stdin handles. The process's copies of the inherited stdout and stdin handles. The
stderr handle is shared among all children and is closed by stderr handle is shared among all children and is closed by
kwsysProcess_Execute after all children have been created. */ kwsysProcess_Execute after all children have been created. */
kwsysProcessCleanupHandle(&si->StartupInfo.hStdInput); kwsysProcessCleanupHandleSafe(&si->StartupInfo.hStdInput,
kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput); STD_INPUT_HANDLE);
kwsysProcessCleanupHandleSafe(&si->StartupInfo.hStdOutput,
STD_OUTPUT_HANDLE);
return 1; return 1;
} }
@ -1984,13 +1997,27 @@ int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name)
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle) 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. */ /* Cleanup the previous handle. */
kwsysProcessCleanupHandle(handle); kwsysProcessCleanupHandle(handle);
/* Duplicate the standard handle to be sure it is inherited and can /* If the standard handle is not inherited then duplicate it to
be closed later. Do not close the original handle when create an inherited copy. Do not close the original handle when
duplicating! */ duplicating! */
if(DuplicateHandle(GetCurrentProcess(), GetStdHandle(nStdHandle), if(inherited)
{
*handle = GetStdHandle(nStdHandle);
return 1;
}
else if(DuplicateHandle(GetCurrentProcess(), GetStdHandle(nStdHandle),
GetCurrentProcess(), handle, GetCurrentProcess(), handle,
0, TRUE, DUPLICATE_SAME_ACCESS)) 0, TRUE, DUPLICATE_SAME_ACCESS))
{ {
@ -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. */ /* Close all handles created by kwsysProcess_Execute. */
void kwsysProcessCleanup(kwsysProcess* cp, int error) void kwsysProcessCleanup(kwsysProcess* cp, int error)
{ {