ENH: Added windows implementation of Disown/Detach.
This commit is contained in:
parent
55c1c3b33f
commit
1d6eecd949
|
@ -102,6 +102,7 @@ static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTi
|
||||||
static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2);
|
static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2);
|
||||||
static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
|
static void kwsysProcessSetExitException(kwsysProcess* cp, int code);
|
||||||
static void kwsysProcessKillTree(int pid);
|
static void kwsysProcessKillTree(int pid);
|
||||||
|
static void kwsysProcessDisablePipeThreads(kwsysProcess* cp);
|
||||||
extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname);
|
extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname);
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
@ -165,6 +166,12 @@ struct kwsysProcess_s
|
||||||
/* The working directory for the child process. */
|
/* The working directory for the child process. */
|
||||||
char* WorkingDirectory;
|
char* WorkingDirectory;
|
||||||
|
|
||||||
|
/* Whether to create the child as a detached process. */
|
||||||
|
int OptionDetach;
|
||||||
|
|
||||||
|
/* Whether the child was created as a detached process. */
|
||||||
|
int Detached;
|
||||||
|
|
||||||
/* Whether to hide the child process's window. */
|
/* Whether to hide the child process's window. */
|
||||||
int HideWindow;
|
int HideWindow;
|
||||||
|
|
||||||
|
@ -460,7 +467,14 @@ void kwsysProcess_Delete(kwsysProcess* cp)
|
||||||
/* If the process is executing, wait for it to finish. */
|
/* If the process is executing, wait for it to finish. */
|
||||||
if(cp->State == kwsysProcess_State_Executing)
|
if(cp->State == kwsysProcess_State_Executing)
|
||||||
{
|
{
|
||||||
kwsysProcess_WaitForExit(cp, 0);
|
if(cp->Detached)
|
||||||
|
{
|
||||||
|
kwsysProcess_Disown(cp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kwsysProcess_WaitForExit(cp, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We are deleting the kwsysProcess instance. */
|
/* We are deleting the kwsysProcess instance. */
|
||||||
|
@ -869,6 +883,7 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
|
||||||
|
|
||||||
switch(optionId)
|
switch(optionId)
|
||||||
{
|
{
|
||||||
|
case kwsysProcess_Option_Detach: return cp->OptionDetach;
|
||||||
case kwsysProcess_Option_HideWindow: return cp->HideWindow;
|
case kwsysProcess_Option_HideWindow: return cp->HideWindow;
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
|
@ -884,6 +899,7 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value)
|
||||||
|
|
||||||
switch(optionId)
|
switch(optionId)
|
||||||
{
|
{
|
||||||
|
case kwsysProcess_Option_Detach: cp->OptionDetach = value; break;
|
||||||
case kwsysProcess_Option_HideWindow: cp->HideWindow = value; break;
|
case kwsysProcess_Option_HideWindow: cp->HideWindow = value; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
@ -1134,13 +1150,35 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
||||||
|
|
||||||
/* The process has now started. */
|
/* The process has now started. */
|
||||||
cp->State = kwsysProcess_State_Executing;
|
cp->State = kwsysProcess_State_Executing;
|
||||||
|
cp->Detached = cp->OptionDetach;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
void kwsysProcess_Disown(kwsysProcess* cp)
|
void kwsysProcess_Disown(kwsysProcess* cp)
|
||||||
{
|
{
|
||||||
/* TODO: Implement windows version. */
|
int i;
|
||||||
(void)cp;
|
|
||||||
|
/* Make sure we are executing a detached process. */
|
||||||
|
if(!cp || !cp->Detached || cp->State != kwsysProcess_State_Executing ||
|
||||||
|
cp->TimeoutExpired || cp->Killed || cp->Terminated)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Disable the reading threads. */
|
||||||
|
kwsysProcessDisablePipeThreads(cp);
|
||||||
|
|
||||||
|
/* Wait for all pipe threads to reset. */
|
||||||
|
for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
|
||||||
|
{
|
||||||
|
WaitForSingleObject(cp->Pipe[i].Reset, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We will not wait for exit, so cleanup now. */
|
||||||
|
kwsysProcessCleanup(cp, 0);
|
||||||
|
|
||||||
|
/* The process has been disowned. */
|
||||||
|
cp->State = kwsysProcess_State_Disowned;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
@ -1373,31 +1411,8 @@ void kwsysProcess_Kill(kwsysProcess* cp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we are killing a process that just reported data, release
|
/* Disable the reading threads. */
|
||||||
the pipe's thread. */
|
kwsysProcessDisablePipeThreads(cp);
|
||||||
if(cp->CurrentIndex < KWSYSPE_PIPE_COUNT)
|
|
||||||
{
|
|
||||||
ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Empty, 1, 0);
|
|
||||||
cp->CurrentIndex = KWSYSPE_PIPE_COUNT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Wake up all the pipe threads with dummy data. */
|
|
||||||
for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
|
|
||||||
{
|
|
||||||
DWORD dummy;
|
|
||||||
WriteFile(cp->Pipe[i].Write, "", 1, &dummy, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tell pipe threads to reset until we run another process. */
|
|
||||||
while(cp->PipesLeft > 0)
|
|
||||||
{
|
|
||||||
WaitForSingleObject(cp->Full, INFINITE);
|
|
||||||
cp->CurrentIndex = cp->SharedIndex;
|
|
||||||
ReleaseSemaphore(cp->SharedIndexMutex, 1, 0);
|
|
||||||
cp->Pipe[cp->CurrentIndex].Closed = 1;
|
|
||||||
ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Empty, 1, 0);
|
|
||||||
--cp->PipesLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Kill the children. */
|
/* Kill the children. */
|
||||||
cp->Killed = 1;
|
cp->Killed = 1;
|
||||||
|
@ -2542,3 +2557,34 @@ static void kwsysProcessKillTree(int pid)
|
||||||
kwsysProcess_List_Delete(plist);
|
kwsysProcess_List_Delete(plist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static void kwsysProcessDisablePipeThreads(kwsysProcess* cp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* If data were just reported data, release the pipe's thread. */
|
||||||
|
if(cp->CurrentIndex < KWSYSPE_PIPE_COUNT)
|
||||||
|
{
|
||||||
|
ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Empty, 1, 0);
|
||||||
|
cp->CurrentIndex = KWSYSPE_PIPE_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wake up all the pipe threads with dummy data. */
|
||||||
|
for(i=0; i < KWSYSPE_PIPE_COUNT; ++i)
|
||||||
|
{
|
||||||
|
DWORD dummy;
|
||||||
|
WriteFile(cp->Pipe[i].Write, "", 1, &dummy, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tell pipe threads to reset until we run another process. */
|
||||||
|
while(cp->PipesLeft > 0)
|
||||||
|
{
|
||||||
|
WaitForSingleObject(cp->Full, INFINITE);
|
||||||
|
cp->CurrentIndex = cp->SharedIndex;
|
||||||
|
ReleaseSemaphore(cp->SharedIndexMutex, 1, 0);
|
||||||
|
cp->Pipe[cp->CurrentIndex].Closed = 1;
|
||||||
|
ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Empty, 1, 0);
|
||||||
|
--cp->PipesLeft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue