diff options
Diffstat (limited to 'Source/kwsys/ProcessUNIX.c')
-rw-r--r-- | Source/kwsys/ProcessUNIX.c | 93 |
1 files changed, 54 insertions, 39 deletions
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 6f3d3df..d6d7fcb 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -141,6 +141,7 @@ typedef struct kwsysProcessCreateInformation_s static int kwsysProcessInitialize(kwsysProcess* cp); static void kwsysProcessCleanup(kwsysProcess* cp, int error); static void kwsysProcessCleanupDescriptor(int* pfd); +static void kwsysProcessClosePipes(kwsysProcess* cp); static int kwsysProcessSetNonBlocking(int fd); static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, kwsysProcessCreateInformation* si, int* readEnd); @@ -893,8 +894,6 @@ void kwsysProcess_Execute(kwsysProcess* cp) /*--------------------------------------------------------------------------*/ kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp) { - int i; - /* Make sure a detached child process is running. */ if(!cp || !cp->Detached || cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired || cp->Killed) @@ -902,33 +901,8 @@ kwsysEXPORT void kwsysProcess_Disown(kwsysProcess* cp) return; } - /* Close any pipes that are still open. */ - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - if(cp->PipeReadEnds[i] >= 0) - { -#if KWSYSPE_USE_SELECT - /* If the pipe was reported by the last call to select, we must - read from it. This is needed to satisfy the suggestions from - "man select_tut" and is not needed for the polling - implementation. Ignore the data. */ - if(FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet)) - { - /* We are handling this pipe now. Remove it from the set. */ - FD_CLR(cp->PipeReadEnds[i], &cp->PipeSet); - - /* The pipe is ready to read without blocking. Keep trying to - read until the operation is not interrupted. */ - while((read(cp->PipeReadEnds[i], cp->PipeBuffer, - KWSYSPE_PIPE_BUFFER_SIZE) < 0) && (errno == EINTR)); - } -#endif - - /* We are done reading from this pipe. */ - kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); - --cp->PipesLeft; - } - } + /* Close all the pipes safely. */ + kwsysProcessClosePipes(cp); /* We will not wait for exit, so cleanup now. */ kwsysProcessCleanup(cp, 0); @@ -1346,18 +1320,17 @@ void kwsysProcess_Kill(kwsysProcess* cp) return; } + /* First close the child exit report pipe write end to avoid causing a + SIGPIPE when the child terminates and our signal handler tries to + report it after we have already closed the read end. */ + kwsysProcessCleanupDescriptor(&cp->SignalPipe); + +#if !defined(__APPLE__) /* Close all the pipe read ends. Do this before killing the children because Cygwin has problems killing processes that are - blocking to wait for writing to their output pipes. First close - the child exit report pipe write end to avoid causing a SIGPIPE - when the child terminates and our signal handler tries to report - it. */ - kwsysProcessCleanupDescriptor(&cp->SignalPipe); - for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) - { - kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); - } - cp->PipesLeft = 0; + blocking to wait for writing to their output pipes. */ + kwsysProcessClosePipes(cp); +#endif /* Kill the children. */ cp->Killed = 1; @@ -1374,6 +1347,14 @@ void kwsysProcess_Kill(kwsysProcess* cp) while((waitpid(cp->ForkPIDs[i], &status, 0) < 0) && (errno == EINTR)); } } + +#if defined(__APPLE__) + /* Close all the pipe read ends. Do this after killing the + children because OS X has problems closing pipe read ends whose + pipes are full and still have an open write end. */ + kwsysProcessClosePipes(cp); +#endif + cp->CommandsLeft = 0; } @@ -1534,6 +1515,40 @@ static void kwsysProcessCleanupDescriptor(int* pfd) } /*--------------------------------------------------------------------------*/ +static void kwsysProcessClosePipes(kwsysProcess* cp) +{ + int i; + + /* Close any pipes that are still open. */ + for(i=0; i < KWSYSPE_PIPE_COUNT; ++i) + { + if(cp->PipeReadEnds[i] >= 0) + { +#if KWSYSPE_USE_SELECT + /* If the pipe was reported by the last call to select, we must + read from it. This is needed to satisfy the suggestions from + "man select_tut" and is not needed for the polling + implementation. Ignore the data. */ + if(FD_ISSET(cp->PipeReadEnds[i], &cp->PipeSet)) + { + /* We are handling this pipe now. Remove it from the set. */ + FD_CLR(cp->PipeReadEnds[i], &cp->PipeSet); + + /* The pipe is ready to read without blocking. Keep trying to + read until the operation is not interrupted. */ + while((read(cp->PipeReadEnds[i], cp->PipeBuffer, + KWSYSPE_PIPE_BUFFER_SIZE) < 0) && (errno == EINTR)); + } +#endif + + /* We are done reading from this pipe. */ + kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); + --cp->PipesLeft; + } + } +} + +/*--------------------------------------------------------------------------*/ static int kwsysProcessSetNonBlocking(int fd) { int flags = fcntl(fd, F_GETFL); |