ENH: Added SetPipeShared method to allow stdout and stderr pipes to be shared with the parent process.
This commit is contained in:
parent
ab0a30e2b3
commit
802601b606
|
@ -31,6 +31,7 @@
|
|||
#define kwsysProcess_SetTimeout kwsys(Process_SetTimeout)
|
||||
#define kwsysProcess_SetWorkingDirectory kwsys(Process_SetWorkingDirectory)
|
||||
#define kwsysProcess_SetPipeFile kwsys(Process_SetPipeFile)
|
||||
#define kwsysProcess_SetPipeShared kwsys(Process_SetPipeShared)
|
||||
#define kwsysProcess_Option_HideWindow kwsys(Process_Option_HideWindow)
|
||||
#define kwsysProcess_GetOption kwsys(Process_GetOption)
|
||||
#define kwsysProcess_SetOption kwsys(Process_SetOption)
|
||||
|
@ -129,6 +130,14 @@ kwsysEXPORT int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp,
|
|||
kwsysEXPORT int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe,
|
||||
const char* file);
|
||||
|
||||
/**
|
||||
* Set whether the given pipe in the child is shared with the parent
|
||||
* process. The default is no for Pipe_STDOUT and Pipe_STDERR and yes
|
||||
* for Pipe_STDIN.
|
||||
*/
|
||||
kwsysEXPORT void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe,
|
||||
int shared);
|
||||
|
||||
/**
|
||||
* Get/Set a platform-specific option. Possible options are:
|
||||
*
|
||||
|
@ -301,6 +310,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
|
|||
# undef kwsysProcess_SetTimeout
|
||||
# undef kwsysProcess_SetWorkingDirectory
|
||||
# undef kwsysProcess_SetPipeFile
|
||||
# undef kwsysProcess_SetPipeShared
|
||||
# undef kwsysProcess_Option_HideWindow
|
||||
# undef kwsysProcess_GetOption
|
||||
# undef kwsysProcess_SetOption
|
||||
|
|
|
@ -169,6 +169,11 @@ struct kwsysProcess_s
|
|||
char* PipeFileSTDOUT;
|
||||
char* PipeFileSTDERR;
|
||||
|
||||
/* Whether each pipe is shared with the parent process. */
|
||||
int PipeSharedSTDIN;
|
||||
int PipeSharedSTDOUT;
|
||||
int PipeSharedSTDERR;
|
||||
|
||||
/* The real working directory of this process. */
|
||||
int RealWorkingDirectoryLength;
|
||||
char* RealWorkingDirectory;
|
||||
|
@ -184,7 +189,13 @@ kwsysProcess* kwsysProcess_New()
|
|||
return 0;
|
||||
}
|
||||
memset(cp, 0, sizeof(kwsysProcess));
|
||||
|
||||
/* Share stdin with the parent process by default. */
|
||||
cp->PipeSharedSTDIN = 1;
|
||||
|
||||
/* Set initial status. */
|
||||
cp->State = kwsysProcess_State_Starting;
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
|
@ -393,9 +404,38 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
|
|||
}
|
||||
strcpy(*pfile, file);
|
||||
}
|
||||
|
||||
/* If we are redirecting the pipe, do not share it. */
|
||||
if(*pfile)
|
||||
{
|
||||
kwsysProcess_SetPipeShared(cp, pipe, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared)
|
||||
{
|
||||
if(!cp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch(pipe)
|
||||
{
|
||||
case kwsysProcess_Pipe_STDIN: cp->PipeSharedSTDIN = shared?1:0; break;
|
||||
case kwsysProcess_Pipe_STDOUT: cp->PipeSharedSTDOUT = shared?1:0; break;
|
||||
case kwsysProcess_Pipe_STDERR: cp->PipeSharedSTDERR = shared?1:0; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
/* If we are sharing the pipe, do not redirect it to a file. */
|
||||
if(shared)
|
||||
{
|
||||
kwsysProcess_SetPipeFile(cp, pipe, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
|
||||
{
|
||||
|
@ -545,6 +585,14 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
|||
}
|
||||
}
|
||||
|
||||
/* Replace the stderr pipe with the parent's if requested. In this
|
||||
case the select call will report that stderr is closed
|
||||
immediately. */
|
||||
if(cp->PipeSharedSTDERR)
|
||||
{
|
||||
kwsysProcessCleanupDescriptor(&si.StdErr);
|
||||
si.StdErr = 2;
|
||||
}
|
||||
|
||||
/* The timeout period starts now. */
|
||||
cp->StartTime = kwsysProcessTimeGetCurrent();
|
||||
|
@ -553,7 +601,7 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
|||
|
||||
/* Create the pipeline of processes. */
|
||||
{
|
||||
int readEnd = 0;
|
||||
int readEnd = -1;
|
||||
for(i=0; i < cp->NumberOfCommands; ++i)
|
||||
{
|
||||
if(!kwsysProcessCreate(cp, i, &si, &readEnd))
|
||||
|
@ -562,13 +610,19 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
|||
|
||||
/* Release resources that may have been allocated for this
|
||||
process before an error occurred. */
|
||||
if(i > 0 || si.StdIn > 0)
|
||||
kwsysProcessCleanupDescriptor(&readEnd);
|
||||
if(si.StdIn != 0)
|
||||
{
|
||||
kwsysProcessCleanupDescriptor(&si.StdIn);
|
||||
}
|
||||
kwsysProcessCleanupDescriptor(&readEnd);
|
||||
kwsysProcessCleanupDescriptor(&si.StdOut);
|
||||
kwsysProcessCleanupDescriptor(&si.StdErr);
|
||||
if(si.StdOut != 1)
|
||||
{
|
||||
kwsysProcessCleanupDescriptor(&si.StdOut);
|
||||
}
|
||||
if(si.StdErr != 2)
|
||||
{
|
||||
kwsysProcessCleanupDescriptor(&si.StdErr);
|
||||
}
|
||||
kwsysProcessCleanupDescriptor(&si.TermPipe);
|
||||
kwsysProcessCleanupDescriptor(&si.ErrorPipe[0]);
|
||||
kwsysProcessCleanupDescriptor(&si.ErrorPipe[1]);
|
||||
|
@ -1106,10 +1160,14 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
else if(cp->PipeSharedSTDIN)
|
||||
{
|
||||
si->StdIn = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
si->StdIn = -1;
|
||||
}
|
||||
|
||||
/* Setup the process's stdout. */
|
||||
{
|
||||
|
@ -1140,6 +1198,15 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
|
|||
}
|
||||
}
|
||||
|
||||
/* Replace the stdout pipe with the parent's if requested. In this
|
||||
case the select call will report that stderr is closed
|
||||
immediately. */
|
||||
if(index == cp->NumberOfCommands-1 && cp->PipeSharedSTDOUT)
|
||||
{
|
||||
kwsysProcessCleanupDescriptor(&si->StdOut);
|
||||
si->StdOut = 1;
|
||||
}
|
||||
|
||||
/* Create the error reporting pipe. */
|
||||
if(pipe(si->ErrorPipe) < 0)
|
||||
{
|
||||
|
@ -1165,12 +1232,22 @@ static int kwsysProcessCreate(kwsysProcess* cp, int index,
|
|||
close(si->ErrorPipe[0]);
|
||||
|
||||
/* Setup the stdin, stdout, and stderr pipes. */
|
||||
if(index > 0 || si->StdIn > 0)
|
||||
if(si->StdIn > 0)
|
||||
{
|
||||
dup2(si->StdIn, 0);
|
||||
}
|
||||
dup2(si->StdOut, 1);
|
||||
dup2(si->StdErr, 2);
|
||||
else if(si->StdIn < 0)
|
||||
{
|
||||
close(0);
|
||||
}
|
||||
if(si->StdOut != 1)
|
||||
{
|
||||
dup2(si->StdOut, 1);
|
||||
}
|
||||
if(si->StdErr != 2)
|
||||
{
|
||||
dup2(si->StdErr, 2);
|
||||
}
|
||||
|
||||
/* Clear the close-on-exec flag for stdin, stdout, and stderr.
|
||||
Also clear it for the termination pipe. All other pipe handles
|
||||
|
|
|
@ -184,6 +184,11 @@ struct kwsysProcess_s
|
|||
char* PipeFileSTDOUT;
|
||||
char* PipeFileSTDERR;
|
||||
|
||||
/* Whether each pipe is shared with the parent process. */
|
||||
int PipeSharedSTDIN;
|
||||
int PipeSharedSTDOUT;
|
||||
int PipeSharedSTDERR;
|
||||
|
||||
/* Handle to automatically delete the Win9x forwarding executable. */
|
||||
HANDLE Win9xHandle;
|
||||
|
||||
|
@ -264,6 +269,9 @@ kwsysProcess* kwsysProcess_New()
|
|||
}
|
||||
ZeroMemory(cp, sizeof(*cp));
|
||||
|
||||
/* Share stdin with the parent process by default. */
|
||||
cp->PipeSharedSTDIN = 1;
|
||||
|
||||
/* Set initial status. */
|
||||
cp->State = kwsysProcess_State_Starting;
|
||||
|
||||
|
@ -805,9 +813,39 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
|
|||
}
|
||||
strcpy(*pfile, file);
|
||||
}
|
||||
|
||||
/* If we are redirecting the pipe, do not share it. */
|
||||
if(*pfile)
|
||||
{
|
||||
kwsysProcess_SetPipeShared(cp, pipe, 0);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void kwsysProcess_SetPipeShared(kwsysProcess* cp, int pipe, int shared)
|
||||
{
|
||||
if(!cp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch(pipe)
|
||||
{
|
||||
case kwsysProcess_Pipe_STDIN: cp->PipeSharedSTDIN = shared?1:0; break;
|
||||
case kwsysProcess_Pipe_STDOUT: cp->PipeSharedSTDOUT = shared?1:0; break;
|
||||
case kwsysProcess_Pipe_STDERR: cp->PipeSharedSTDERR = shared?1:0; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
/* If we are sharing the pipe, do not redirect it to a file. */
|
||||
if(shared)
|
||||
{
|
||||
kwsysProcess_SetPipeFile(cp, pipe, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int kwsysProcess_GetOption(kwsysProcess* cp, int optionId)
|
||||
{
|
||||
|
@ -973,6 +1011,15 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
|||
}
|
||||
}
|
||||
|
||||
/* Replace the stderr pipe with the parent process's if requested.
|
||||
In this case the pipe thread will still run but never report
|
||||
data. */
|
||||
if(cp->PipeSharedSTDERR)
|
||||
{
|
||||
kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
|
||||
si.StartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||
}
|
||||
|
||||
/* Create the pipeline of processes. */
|
||||
{
|
||||
HANDLE readEnd = 0;
|
||||
|
@ -989,12 +1036,18 @@ void kwsysProcess_Execute(kwsysProcess* cp)
|
|||
/* Release resources that may have been allocated for this
|
||||
process before an error occurred. */
|
||||
kwsysProcessCleanupHandle(&readEnd);
|
||||
if(i > 0)
|
||||
if(si.StartupInfo.hStdInput != GetStdHandle(STD_INPUT_HANDLE))
|
||||
{
|
||||
kwsysProcessCleanupHandle(&si.StartupInfo.hStdInput);
|
||||
}
|
||||
kwsysProcessCleanupHandle(&si.StartupInfo.hStdOutput);
|
||||
kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
|
||||
if(si.StartupInfo.hStdOutput != GetStdHandle(STD_OUTPUT_HANDLE))
|
||||
{
|
||||
kwsysProcessCleanupHandle(&si.StartupInfo.hStdOutput);
|
||||
}
|
||||
if(si.StartupInfo.hStdOutput != GetStdHandle(STD_ERROR_HANDLE))
|
||||
{
|
||||
kwsysProcessCleanupHandle(&si.StartupInfo.hStdError);
|
||||
}
|
||||
kwsysProcessCleanupHandle(&si.ErrorPipeRead);
|
||||
kwsysProcessCleanupHandle(&si.ErrorPipeWrite);
|
||||
return;
|
||||
|
@ -1533,10 +1586,14 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
|
|||
}
|
||||
si->StartupInfo.hStdInput = fin;
|
||||
}
|
||||
else
|
||||
else if(cp->PipeSharedSTDIN)
|
||||
{
|
||||
si->StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
si->StartupInfo.hStdInput = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/* Setup the process's stdout. */
|
||||
{
|
||||
|
@ -1578,6 +1635,15 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
|
|||
}
|
||||
}
|
||||
|
||||
/* Replace the stdout pipe with the parent process's if requested.
|
||||
In this case the pipe thread will still run but never report
|
||||
data. */
|
||||
if(index == cp->NumberOfCommands-1 && cp->PipeSharedSTDOUT)
|
||||
{
|
||||
kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput);
|
||||
si->StartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
}
|
||||
|
||||
/* Create the child process. */
|
||||
{
|
||||
BOOL r;
|
||||
|
@ -1678,8 +1744,11 @@ int kwsysProcessCreate(kwsysProcess* cp, int index,
|
|||
kwsysProcessCleanupHandle(&si->StartupInfo.hStdInput);
|
||||
}
|
||||
|
||||
/* The parent process does not need the inhertied pipe write end. */
|
||||
kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput);
|
||||
if(si->StartupInfo.hStdOutput != GetStdHandle(STD_OUTPUT_HANDLE))
|
||||
{
|
||||
/* The parent process does not need the inhertied pipe write end. */
|
||||
kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue