diff options
author | Miguel Sofer <miguel.sofer@gmail.com> | 2007-11-10 16:08:08 (GMT) |
---|---|---|
committer | Miguel Sofer <miguel.sofer@gmail.com> | 2007-11-10 16:08:08 (GMT) |
commit | 0e7fa3edd23cef23c43109db2656ccc52978c99b (patch) | |
tree | a9e86cd8a43c61ca632591c69b5c3b042f0219ca /generic/tclBasic.c | |
parent | 9f42d64486d78ab2ab370e552ded7578ed2966c6 (diff) | |
download | tcl-0e7fa3edd23cef23c43109db2656ccc52978c99b.zip tcl-0e7fa3edd23cef23c43109db2656ccc52978c99b.tar.gz tcl-0e7fa3edd23cef23c43109db2656ccc52978c99b.tar.bz2 |
* generic/tclBasic.c:
* generic/tclInt.h:
* unix/tclUnixInit.c:
* unix/tclUnixPort.h:
* win/tclWin32Dll.c: modify the stack checking algorithm to
recheck in case of failure. The working assumptions are now that
(a) a thread's stack is never moved, and (b) a thread's stack can
grow but not shrink. Port to windows - could be more efficient,
but is already cheaper than it was.
Diffstat (limited to 'generic/tclBasic.c')
-rw-r--r-- | generic/tclBasic.c | 44 |
1 files changed, 20 insertions, 24 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 09ec05d..2684986 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -14,7 +14,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclBasic.c,v 1.272 2007/11/10 03:40:17 das Exp $ + * RCS: @(#) $Id: tclBasic.c,v 1.273 2007/11/10 16:08:09 msofer Exp $ */ #include "tclInt.h" @@ -334,33 +334,20 @@ static const OpCmdInfo mathOpCmds[] = { {0}, NULL } }; -#ifdef TCL_NO_STACK_CHECK -#define CheckStackSpace(interp, localIntPtr) 1 -#else /* stack check enabled */ -#ifdef _TCLUNIXPORT -/* - * A unix system: cache the stack check parameters. - */ - +#ifndef TCL_NO_STACK_CHECK static int stackGrowsDown = 1; #define GetCStackParams(iPtr) \ - stackGrowsDown = TclpGetCStackParams(&(iPtr)->stackBound) + stackGrowsDown = TclpGetCStackParams(&((iPtr)->stackBoundPtr)) #define CheckStackSpace(iPtr, localIntPtr) \ (stackGrowsDown \ - ? ((localIntPtr) > (iPtr)->stackBound) \ - : ((localIntPtr) < (iPtr)->stackBound) \ + ? ((localIntPtr) > *((iPtr)->stackBoundPtr)) \ + : ((localIntPtr) < *((iPtr)->stackBoundPtr)) \ ) -#else /* not unix */ -/* - * FIXME: can we do something similar for other platforms, especially windows? - */ - -#define GetCStackParams(iPtr) -#define CheckStackSpace(interp, localIntPtr) \ - TclpCheckStackSpace() -#endif +#else /* stack check disabled: make them noops */ +#define CheckStackSpace(interp, localIntPtr) 1 +#define GetCStackParams(iPtr) #endif @@ -3420,7 +3407,7 @@ int TclInterpReady( Tcl_Interp *interp) { - int localInt; /* used for checking the stack */ + int localInt, stackOverflow; /* used for checking the stack */ register Interp *iPtr = (Interp *) interp; /* @@ -3448,8 +3435,17 @@ TclInterpReady( * probably because of an infinite loop somewhere. */ - if (((iPtr->numLevels) > iPtr->maxNestingDepth) - || (CheckStackSpace(iPtr, &localInt) == 0)) { + stackOverflow = !CheckStackSpace(iPtr, &localInt); + if (stackOverflow) { + /* + * Update the stack params in case the thread's stack was grown. + */ + + GetCStackParams(iPtr); + stackOverflow = !CheckStackSpace(iPtr, &localInt); + } + + if (stackOverflow || ((iPtr->numLevels) > iPtr->maxNestingDepth)) { Tcl_AppendResult(interp, "too many nested evaluations (infinite loop?)", NULL); return TCL_ERROR; |