From 77806ded9e45e9569f778847e63516f884788da2 Mon Sep 17 00:00:00 2001 From: Joe Mistachkin Date: Thu, 13 Sep 2012 18:30:41 +0000 Subject: Initial work on SF FRQ #3567063. --- win/tclWinThrd.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c index 13fd411..7abcc29 100644 --- a/win/tclWinThrd.c +++ b/win/tclWinThrd.c @@ -13,6 +13,7 @@ #include "tclWinInt.h" #include +#include #include #include @@ -122,6 +123,52 @@ typedef struct WinCondition { struct ThreadSpecificData *lastPtr; } WinCondition; +/* + * The per thread data passed from TclpThreadCreate + * to TclWinThreadStart. + */ + +typedef struct WinThread { + LPTHREAD_START_ROUTINE lpStartAddress; /* Original startup routine */ + LPVOID lpParameter; /* Original startup data */ + unsigned int fpControl; /* Floating point control word from the + * main thread */ +} WinThread; + + +/* + *---------------------------------------------------------------------- + * + * TclWinThreadStart -- + * + * This procedure is the entry point for all new threads created + * by Tcl on Windows. + * + * Results: + * Various, depending on the result of the wrapped thread start + * routine. + * + * Side effects: + * Arbitrary, since user code is executed. + * + *---------------------------------------------------------------------- + */ + +static DWORD WINAPI +TclWinThreadStart( + LPVOID lpParameter) /* The WinThread structure pointer passed + * from TclpThreadCreate */ +{ + WinThread *winThreadPtr = (WinThread *) lpParameter; + unsigned int fpmask = _MCW_EM | _MCW_RC | _MCW_PC | _MCW_DN; + + if (!winThreadPtr) { + return TCL_ERROR; + } + + _controlfp(winThreadPtr->fpControl, fpmask); + return winThreadPtr->lpStartAddress(winThreadPtr->lpParameter); +} /* *---------------------------------------------------------------------- @@ -149,17 +196,22 @@ TclpThreadCreate(idPtr, proc, clientData, stackSize, flags) int flags; /* Flags controlling behaviour of * the new thread */ { + WinThread *winThreadPtr; /* Per-thread startup info */ HANDLE tHandle; + winThreadPtr = (WinThread *)ckalloc(sizeof(WinThread)); + winThreadPtr->lpStartAddress = proc; + winThreadPtr->lpParameter = clientData; + winThreadPtr->fpControl = _controlfp(0, 0); + EnterCriticalSection(&joinLock); #if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__) - tHandle = (HANDLE) _beginthreadex(NULL, (unsigned) stackSize, proc, - clientData, 0, (unsigned *)idPtr); + tHandle = (HANDLE) _beginthreadex(NULL, (unsigned) stackSize, + TclWinThreadStart, winThreadPtr, 0, (unsigned *)idPtr); #else tHandle = CreateThread(NULL, (DWORD) stackSize, - (LPTHREAD_START_ROUTINE) proc, (LPVOID) clientData, - (DWORD) 0, (LPDWORD)idPtr); + TclWinThreadStart, winThreadPtr, 0, (LPDWORD)idPtr); #endif if (tHandle == NULL) { -- cgit v0.12 From c02b64e20cd435142d5924015fadc8dbcd19aa43 Mon Sep 17 00:00:00 2001 From: Joe Mistachkin Date: Thu, 13 Sep 2012 18:37:55 +0000 Subject: Free the WinThread structure before running the original thread procedure. --- win/tclWinThrd.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c index 7abcc29..86ff6a5 100644 --- a/win/tclWinThrd.c +++ b/win/tclWinThrd.c @@ -161,13 +161,20 @@ TclWinThreadStart( { WinThread *winThreadPtr = (WinThread *) lpParameter; unsigned int fpmask = _MCW_EM | _MCW_RC | _MCW_PC | _MCW_DN; + LPTHREAD_START_ROUTINE lpOrigStartAddress; + LPVOID lpOrigParameter; if (!winThreadPtr) { return TCL_ERROR; } _controlfp(winThreadPtr->fpControl, fpmask); - return winThreadPtr->lpStartAddress(winThreadPtr->lpParameter); + + lpOrigStartAddress = winThreadPtr->lpStartAddress; + lpOrigParameter = winThreadPtr->lpParameter; + + ckfree((char *)winThreadPtr); + return lpOrigStartAddress(lpOrigParameter); } /* -- cgit v0.12 From 9d29fc1ebfbb48cc19bf87541750abfbaeab3c31 Mon Sep 17 00:00:00 2001 From: Joe Mistachkin Date: Thu, 13 Sep 2012 20:03:01 +0000 Subject: Make compilation of the fp control changes possible with MinGW. --- win/tclWinThrd.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/win/tclWinThrd.c b/win/tclWinThrd.c index 86ff6a5..21d422f 100644 --- a/win/tclWinThrd.c +++ b/win/tclWinThrd.c @@ -160,7 +160,7 @@ TclWinThreadStart( * from TclpThreadCreate */ { WinThread *winThreadPtr = (WinThread *) lpParameter; - unsigned int fpmask = _MCW_EM | _MCW_RC | _MCW_PC | _MCW_DN; + unsigned int fpmask; LPTHREAD_START_ROUTINE lpOrigStartAddress; LPVOID lpOrigParameter; @@ -168,6 +168,12 @@ TclWinThreadStart( return TCL_ERROR; } + fpmask = _MCW_EM | _MCW_RC | _MCW_PC; + +#if defined(_MSC_VER) && _MSC_VER >= 1200 + fpmask |= _MCW_DN; +#endif + _controlfp(winThreadPtr->fpControl, fpmask); lpOrigStartAddress = winThreadPtr->lpStartAddress; @@ -207,7 +213,7 @@ TclpThreadCreate(idPtr, proc, clientData, stackSize, flags) HANDLE tHandle; winThreadPtr = (WinThread *)ckalloc(sizeof(WinThread)); - winThreadPtr->lpStartAddress = proc; + winThreadPtr->lpStartAddress = (LPTHREAD_START_ROUTINE) proc; winThreadPtr->lpParameter = clientData; winThreadPtr->fpControl = _controlfp(0, 0); @@ -215,7 +221,8 @@ TclpThreadCreate(idPtr, proc, clientData, stackSize, flags) #if defined(_MSC_VER) || defined(__MSVCRT__) || defined(__BORLANDC__) tHandle = (HANDLE) _beginthreadex(NULL, (unsigned) stackSize, - TclWinThreadStart, winThreadPtr, 0, (unsigned *)idPtr); + (Tcl_ThreadCreateProc*) TclWinThreadStart, winThreadPtr, + 0, (unsigned *)idPtr); #else tHandle = CreateThread(NULL, (DWORD) stackSize, TclWinThreadStart, winThreadPtr, 0, (LPDWORD)idPtr); -- cgit v0.12 From de5687769c8034c6d0d32e207f9934e3a3fed533 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 3 Oct 2012 15:18:32 +0000 Subject: When checking for std channels being closed, compare the channel state, not the channel itself so that stacked channels do not cause trouble. --- ChangeLog | 6 ++++++ generic/tclIO.c | 44 ++++++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index b8b9f2b..6f84707 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-10-03 Don Porter + + * generic/tclIO.c: When checking for std channels being closed, + compare the channel state, not the channel itself so that stacked + channels do not cause trouble. + 2012-08-17 Jan Nijtmans * win/nmakehlp.c: Add "-V" option, in order to be able diff --git a/generic/tclIO.c b/generic/tclIO.c index b9cd30c..eace472 100644 --- a/generic/tclIO.c +++ b/generic/tclIO.c @@ -697,26 +697,30 @@ CheckForStdChannelsBeingClosed(chan) ChannelState *statePtr = ((Channel *) chan)->state; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - if ((chan == tsdPtr->stdinChannel) && (tsdPtr->stdinInitialized)) { - if (statePtr->refCount < 2) { - statePtr->refCount = 0; - tsdPtr->stdinChannel = NULL; - return; - } - } else if ((chan == tsdPtr->stdoutChannel) - && (tsdPtr->stdoutInitialized)) { - if (statePtr->refCount < 2) { - statePtr->refCount = 0; - tsdPtr->stdoutChannel = NULL; - return; - } - } else if ((chan == tsdPtr->stderrChannel) - && (tsdPtr->stderrInitialized)) { - if (statePtr->refCount < 2) { - statePtr->refCount = 0; - tsdPtr->stderrChannel = NULL; - return; - } + if (tsdPtr->stdinInitialized + && tsdPtr->stdinChannel != NULL + && statePtr == ((Channel *)tsdPtr->stdinChannel)->state) { + if (statePtr->refCount < 2) { + statePtr->refCount = 0; + tsdPtr->stdinChannel = NULL; + return; + } + } else if (tsdPtr->stdoutInitialized + && tsdPtr->stdoutChannel != NULL + && statePtr == ((Channel *)tsdPtr->stdoutChannel)->state) { + if (statePtr->refCount < 2) { + statePtr->refCount = 0; + tsdPtr->stdoutChannel = NULL; + return; + } + } else if (tsdPtr->stderrInitialized + && tsdPtr->stderrChannel != NULL + && statePtr == ((Channel *)tsdPtr->stderrChannel)->state) { + if (statePtr->refCount < 2) { + statePtr->refCount = 0; + tsdPtr->stderrChannel = NULL; + return; + } } } -- cgit v0.12