diff options
author | davygrvy <davygrvy@pobox.com> | 2004-01-20 05:18:22 (GMT) |
---|---|---|
committer | davygrvy <davygrvy@pobox.com> | 2004-01-20 05:18:22 (GMT) |
commit | a4c4ef181236cd0ad81e34dfaf3e6f9c08e12a41 (patch) | |
tree | 8aa9b028bf374d208a7e563e5b53b58e7699c282 /win | |
parent | 4d5446b2dadf9bbe0dfc6c385e6c235a529251c5 (diff) | |
download | tcl-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')
-rw-r--r-- | win/tclWinPipe.c | 19 |
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; |