summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordavygrvy <davygrvy@pobox.com>2005-04-19 16:28:22 (GMT)
committerdavygrvy <davygrvy@pobox.com>2005-04-19 16:28:22 (GMT)
commitdcd2e428a1d1f9e3e9948ec66db8fc00a50f5f78 (patch)
tree26209da071fe74735cc8b3ec35ad52bb1c9cb722
parenta67b1b3bbeb88556675d7fde92fea842d50ef35f (diff)
downloadtcl-dcd2e428a1d1f9e3e9948ec66db8fc00a50f5f78.zip
tcl-dcd2e428a1d1f9e3e9948ec66db8fc00a50f5f78.tar.gz
tcl-dcd2e428a1d1f9e3e9948ec66db8fc00a50f5f78.tar.bz2
* win/tclWinPipe.c: The pipe channel driver now respects
the -blocking option when closing. The windows pipe driver now has the same behavior as the UNIX side. This change is to avoid a hung shell when exiting due to open pipes that refuse to close in a graceful manner. * doc/open.n: Added a note about -blocking 0 and lack of exit status as it had never been documented. [Bug 947693] ***POTENTIAL INCOMPATIBILITY*** Scripts that use async pipes on windows, must (like the UNIX side) set -blocking to 1 before calling [close] to receive the exit status. * tests/winPipe.test (winpipe-6.1/2): added 'fconfigure $f -blocking 1' so the exit status can be acquired.
-rw-r--r--doc/open.n5
-rw-r--r--tests/winPipe.test4
-rw-r--r--win/tclWinPipe.c49
3 files changed, 38 insertions, 20 deletions
diff --git a/doc/open.n b/doc/open.n
index 4322dde..003739b 100644
--- a/doc/open.n
+++ b/doc/open.n
@@ -5,7 +5,7 @@
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
-'\" RCS: @(#) $Id: open.n,v 1.16.2.2 2004/10/27 14:23:57 dkf Exp $
+'\" RCS: @(#) $Id: open.n,v 1.16.2.3 2005/04/19 16:30:21 davygrvy Exp $
'\"
.so man.macros
.TH open n 8.3 Tcl "Tcl Built-In Commands"
@@ -136,7 +136,8 @@ command, using the channel id returned by \fBopen\fR as argument.
If the command (or one of the commands) executed in the command
pipeline returns an error (according to the definition in \fBexec\fR),
a Tcl error is generated when \fBclose\fR is called on the channel
-(similar to the \fBclose\fR command.)
+unless the pipeline is in non-blocking mode then no exit status is
+returned (a silent \fBclose\fR with -blocking 0).
.PP
It is often useful to use the \fBfileevent\fR command with pipelines
so other processing may happen at the same time as running the command
diff --git a/tests/winPipe.test b/tests/winPipe.test
index 4cc6e26..34de9bb 100644
--- a/tests/winPipe.test
+++ b/tests/winPipe.test
@@ -12,7 +12,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: winPipe.test,v 1.22.2.2 2004/10/28 00:01:12 dgp Exp $
+# RCS: @(#) $Id: winPipe.test,v 1.22.2.3 2005/04/19 16:28:34 davygrvy Exp $
package require tcltest
namespace import -force ::tcltest::*
@@ -295,6 +295,7 @@ test winpipe-6.1 {PipeSetupProc & PipeCheckProc: read threads} \
lappend x [read $f]
after 100 { lappend x timeout }
vwait x
+ fconfigure $f -blocking 1
lappend x [catch {close $f} msg] $msg
} {writable timeout readable {foobar
} timeout 1 stderr32}
@@ -309,6 +310,7 @@ test winpipe-6.2 {PipeSetupProc & PipeCheckProc: write threads} \
flush $f
after 100 { lappend x timeout }
vwait x
+ fconfigure $f -blocking 1
lappend x [catch {close $f} msg] $msg
} {writable timeout 0 {}}
diff --git a/win/tclWinPipe.c b/win/tclWinPipe.c
index 57858f0..0206ac5 100644
--- a/win/tclWinPipe.c
+++ b/win/tclWinPipe.c
@@ -9,7 +9,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclWinPipe.c,v 1.33.2.9 2005/01/27 22:53:37 andreas_kupries Exp $
+ * RCS: @(#) $Id: tclWinPipe.c,v 1.33.2.10 2005/04/19 16:28:22 davygrvy Exp $
*/
#include "tclWinInt.h"
@@ -2046,27 +2046,42 @@ PipeClose2Proc(
}
}
- /*
- * Wrap the error file into a channel and give it to the cleanup
- * routine.
- */
+ if ((pipePtr->flags & PIPE_ASYNC) || 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.
+ */
- if (pipePtr->errorFile) {
- WinFile *filePtr;
+ Tcl_DetachPids(pipePtr->numPids, pipePtr->pidPtr);
+ Tcl_ReapDetachedProcs();
- filePtr = (WinFile*)pipePtr->errorFile;
- errChan = Tcl_MakeFileChannel((ClientData) filePtr->handle,
- TCL_READABLE);
- ckfree((char *) filePtr);
+ if (pipePtr->errorFile) {
+ TclpCloseFile(pipePtr->errorFile);
+ }
} else {
- errChan = NULL;
- }
+ /*
+ * Wrap the error file into a channel and give it to the cleanup
+ * routine.
+ */
+
+ if (pipePtr->errorFile) {
+ WinFile *filePtr;
- result = TclCleanupChildren(interp, pipePtr->numPids, pipePtr->pidPtr,
- errChan);
+ filePtr = (WinFile*)pipePtr->errorFile;
+ errChan = Tcl_MakeFileChannel((ClientData) filePtr->handle,
+ TCL_READABLE);
+ ckfree((char *) filePtr);
+ } else {
+ errChan = NULL;
+ }
+
+ result = TclCleanupChildren(interp, pipePtr->numPids,
+ pipePtr->pidPtr, errChan);
+ }
if (pipePtr->numPids > 0) {
- ckfree((char *) pipePtr->pidPtr);
+ ckfree((char *) pipePtr->pidPtr);
}
if (pipePtr->writeBuf != NULL) {
@@ -2076,7 +2091,7 @@ PipeClose2Proc(
ckfree((char*) pipePtr);
if (errorCode == 0) {
- return result;
+ return result;
}
return errorCode;
}