summaryrefslogtreecommitdiffstats
path: root/win/tclWinPipe.c
diff options
context:
space:
mode:
authordavygrvy <davygrvy@pobox.com>2004-01-20 05:18:22 (GMT)
committerdavygrvy <davygrvy@pobox.com>2004-01-20 05:18:22 (GMT)
commita4c4ef181236cd0ad81e34dfaf3e6f9c08e12a41 (patch)
tree8aa9b028bf374d208a7e563e5b53b58e7699c282 /win/tclWinPipe.c
parent4d5446b2dadf9bbe0dfc6c385e6c235a529251c5 (diff)
downloadtcl-a4c4ef181236cd0ad81e34dfaf3e6f9c08e12a41.zip
tcl-a4c4ef181236cd0ad81e34dfaf3e6f9c08e12a41.tar.gz
tcl-a4c4ef181236cd0ad81e34dfaf3e6f9c08e12a41.tar.bz2
* win/tclWinPipe.c (Tcl_WaitPid): 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.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/win/tclWinPipe.c b/win/tclWinPipe.c
index 4edf214..93d4a17 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.39 2003/12/24 04:18:23 davygrvy Exp $
+ * RCS: @(#) $Id: tclWinPipe.c,v 1.40 2004/01/20 05:18:22 davygrvy Exp $
*/
#include "tclWinInt.h"
@@ -906,6 +906,8 @@ TclpGetPid(
{
ProcInfo *infoPtr;
+ PipeInit();
+
Tcl_MutexLock(&pipeMutex);
for (infoPtr = procList; infoPtr != NULL; infoPtr = infoPtr->nextPtr) {
if (infoPtr->hProcess == (HANDLE) pid) {
@@ -2485,7 +2487,7 @@ Tcl_WaitPid(
int *statPtr,
int options)
{
- ProcInfo *infoPtr, **prevPtrPtr;
+ ProcInfo *infoPtr = NULL, **prevPtrPtr;
DWORD flags;
Tcl_Pid result;
DWORD ret, exitCode;
@@ -2502,7 +2504,7 @@ Tcl_WaitPid(
}
/*
- * Find the process on the process list.
+ * Find the process and cut it from the process list.
*/
Tcl_MutexLock(&pipeMutex);
@@ -2510,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;
}
}
@@ -2539,6 +2542,13 @@ Tcl_WaitPid(
if (ret == WAIT_TIMEOUT) {
*statPtr = 0;
if (options & WNOHANG) {
+ /*
+ * Re-insert this infoPtr back on the list.
+ */
+ Tcl_MutexLock(&pipeMutex);
+ infoPtr->nextPtr = procList;
+ procList = infoPtr;
+ Tcl_MutexUnlock(&pipeMutex);
return 0;
} else {
result = 0;
@@ -2601,11 +2611,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;