BUG: Fixed deadlock condition when grandchildren are running after the children exit.
This commit is contained in:
parent
0d594a4538
commit
58e8bfb849
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue