summaryrefslogtreecommitdiffstats
path: root/win/tclWinPipe.c
diff options
context:
space:
mode:
authorandreas_kupries <akupries@shaw.ca>2006-03-14 20:36:36 (GMT)
committerandreas_kupries <akupries@shaw.ca>2006-03-14 20:36:36 (GMT)
commit66e553d72e52824e2bb3f06814e9d3fc6f4a935d (patch)
tree0ffae9e11d14a1eaa9ee089f8880a2351a8427c2 /win/tclWinPipe.c
parent24f992668d4072421af7d022ad5015ab3c29d505 (diff)
downloadtcl-66e553d72e52824e2bb3f06814e9d3fc6f4a935d.zip
tcl-66e553d72e52824e2bb3f06814e9d3fc6f4a935d.tar.gz
tcl-66e553d72e52824e2bb3f06814e9d3fc6f4a935d.tar.bz2
* win/tclWinPipe.c (Tcl_WaitPid): Backport of fix made to the head
by David Gravereaux in 2004. See ChangeLog entry 2004-01-19. [Bug 1381436]. Fixed a thread-safety problem with the process list. The delayed cut operation after the wait was going stale by being outside the list lock. It now cuts within the lock and does a locked splice for when it needs to instead. [Bug 859820]
Diffstat (limited to 'win/tclWinPipe.c')
-rw-r--r--win/tclWinPipe.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/win/tclWinPipe.c b/win/tclWinPipe.c
index e599b50..624aecc 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.16 2006/03/10 14:18:54 vasiljevic Exp $
+ * RCS: @(#) $Id: tclWinPipe.c,v 1.33.2.17 2006/03/14 20:36:39 andreas_kupries Exp $
*/
#include "tclWinInt.h"
@@ -885,6 +885,8 @@ TclpGetPid(
{
ProcInfo *infoPtr;
+ PipeInit();
+
Tcl_MutexLock(&pipeMutex);
for (infoPtr = procList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) {
if (infoPtr->hProcess == (HANDLE) pid) {
@@ -2479,7 +2481,7 @@ Tcl_WaitPid(
int *statPtr,
int options)
{
- ProcInfo *infoPtr, **prevPtrPtr;
+ ProcInfo *infoPtr = NULL, **prevPtrPtr;
DWORD flags;
Tcl_Pid result;
DWORD ret, exitCode;
@@ -2496,7 +2498,13 @@ Tcl_WaitPid(
}
/*
- * Find the process on the process list.
+ * Find the process and cut it from the process list.
+ * SF Tcl Bug 859820, Backport of its fix.
+ * SF Tcl Bug 1381436, asking for the backport.
+ *
+ * [x] Cutting the infoPtr after the closehandle allows the
+ * pointer to become stale. We do it here, and compensate if the
+ * process was not done yet.
*/
Tcl_MutexLock(&pipeMutex);
@@ -2504,6 +2512,7 @@ Tcl_WaitPid(
for (infoPtr = procList; infoPtr != NULL;
prevPtrPtr = &infoPtr->nextPtr, infoPtr = infoPtr->nextPtr) {
if (infoPtr->hProcess == (HANDLE) pid) {
+ *prevPtrPtr = infoPtr->nextPtr;
break;
}
}
@@ -2533,6 +2542,14 @@ Tcl_WaitPid(
if (ret == WAIT_TIMEOUT) {
*statPtr = 0;
if (options & WNOHANG) {
+ /*
+ * Re-insert the cut infoPtr back on the list.
+ * See [x] for explanation.
+ */
+ Tcl_MutexLock(&pipeMutex);
+ infoPtr->nextPtr = procList;
+ procList = infoPtr;
+ Tcl_MutexUnlock(&pipeMutex);
return 0;
} else {
result = 0;
@@ -2591,11 +2608,10 @@ Tcl_WaitPid(
}
/*
- * Remove the process from the process list and close the process handle.
+ * Officially close the process handle.
*/
CloseHandle(infoPtr->hProcess);
- *prevPtrPtr = infoPtr->nextPtr;
ckfree((char*)infoPtr);
return result;