diff options
Diffstat (limited to 'unix/tclUnixPipe.c')
-rw-r--r-- | unix/tclUnixPipe.c | 104 |
1 files changed, 98 insertions, 6 deletions
diff --git a/unix/tclUnixPipe.c b/unix/tclUnixPipe.c index 967d633..0381764 100644 --- a/unix/tclUnixPipe.c +++ b/unix/tclUnixPipe.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclUnixPipe.c,v 1.45 2008/12/12 16:07:18 ferrieux Exp $ + * RCS: @(#) $Id: tclUnixPipe.c,v 1.46 2008/12/18 01:14:17 ferrieux Exp $ */ #include "tclInt.h" @@ -51,8 +51,10 @@ typedef struct PipeState { */ static int PipeBlockModeProc(ClientData instanceData, int mode); -static int PipeCloseProc(ClientData instanceData, - Tcl_Interp *interp); +static int PipeClose2Proc(ClientData instanceData, + Tcl_Interp *interp, int flags); +/* static int PipeCloseProc(ClientData instanceData, + Tcl_Interp *interp); */ static int PipeGetHandleProc(ClientData instanceData, int direction, ClientData *handlePtr); static int PipeInputProc(ClientData instanceData, char *buf, @@ -71,7 +73,7 @@ static int SetupStdFile(TclFile file, int type); static Tcl_ChannelType pipeChannelType = { "pipe", /* Type name. */ TCL_CHANNEL_VERSION_5, /* v5 channel */ - PipeCloseProc, /* Close proc. */ + TCL_CLOSE2PROC, /* Close proc. */ PipeInputProc, /* Input proc. */ PipeOutputProc, /* Output proc. */ NULL, /* Seek proc. */ @@ -79,7 +81,7 @@ static Tcl_ChannelType pipeChannelType = { NULL, /* Get option proc. */ PipeWatchProc, /* Initialize notifier. */ PipeGetHandleProc, /* Get OS handles out of channel. */ - NULL, /* close2proc. */ + PipeClose2Proc, /* close2proc. */ PipeBlockModeProc, /* Set blocking or non-blocking mode.*/ NULL, /* flush proc. */ NULL, /* handler proc. */ @@ -908,7 +910,96 @@ PipeBlockModeProc( /* *---------------------------------------------------------------------- * - * PipeCloseProc -- + * PipeClose2Proc + * + * This function is invoked by the generic IO level to perform + * pipeline-type-specific half or full-close. + * + * Results: + * 0 on success, errno otherwise. + * + * Side effects: + * Closes the command pipeline channel. + * + *---------------------------------------------------------------------- + */ + +static int +PipeClose2Proc( + ClientData instanceData, /* The pipe to close. */ + Tcl_Interp *interp, /* For error reporting. */ + int flags) /* Flags that indicate which side to close. */ +{ + PipeState *pipePtr= (PipeState *) instanceData; + Tcl_Channel errChan; + int errorCode, result; + + errorCode = 0; + result = 0; + + if (((!flags)||(flags & TCL_CLOSE_READ)) && (pipePtr->inFile != NULL)) { + if (TclpCloseFile(pipePtr->inFile) < 0) { + errorCode = errno; + } else { + pipePtr->inFile=NULL; + } + } + if (((!flags)||(flags & TCL_CLOSE_WRITE)) && (pipePtr->outFile != NULL) && (errorCode == 0)) { + if (TclpCloseFile(pipePtr->outFile) < 0) { + errorCode = errno; + } else { + pipePtr->outFile=NULL; + } + } + + /* if half-closing, stop here. */ + if (flags) { + return errorCode; + } + + if (pipePtr->isNonBlocking || TclInExit()) { + /* + * If the channel is non-blocking or Tcl is being cleaned up, just + * detach the children PIDs, reap them (important if we are in a + * dynamic load module), and discard the errorFile. + */ + + Tcl_DetachPids(pipePtr->numPids, pipePtr->pidPtr); + Tcl_ReapDetachedProcs(); + + if (pipePtr->errorFile) { + TclpCloseFile(pipePtr->errorFile); + } + } else { + /* + * Wrap the error file into a channel and give it to the cleanup + * routine. + */ + + if (pipePtr->errorFile) { + errChan = Tcl_MakeFileChannel( + (ClientData) INT2PTR(GetFd(pipePtr->errorFile)), TCL_READABLE); + } else { + errChan = NULL; + } + result = TclCleanupChildren(interp, pipePtr->numPids, pipePtr->pidPtr, + errChan); + } + + if (pipePtr->numPids != 0) { + ckfree((char *) pipePtr->pidPtr); + } + ckfree((char *) pipePtr); + if (errorCode == 0) { + return result; + } + return errorCode; +} + +/* + *---------------------------------------------------------------------- + * + * PipeCloseProc -- OBSOLETE * * This function is invoked by the generic IO level to perform * channel-type-specific cleanup when a command pipeline channel is @@ -936,6 +1027,7 @@ PipeCloseProc( errorCode = 0; result = 0; pipePtr = (PipeState *) instanceData; + if (pipePtr->inFile) { if (TclpCloseFile(pipePtr->inFile) < 0) { errorCode = errno; |