summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--win/tclWinPipe.c26
2 files changed, 32 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index efd6797..6db203f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2006-03-14 Andreas Kupries <andreask@activestate.com>
+
+ * 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]
+
2006-03-13 Don Porter <dgp@users.sourceforge.net>
* generic/tclEncoding.c: Report error when an escape encoding
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;