summaryrefslogtreecommitdiffstats
path: root/generic/tclBasic.c
diff options
context:
space:
mode:
authorMiguel Sofer <miguel.sofer@gmail.com>2007-11-10 16:08:08 (GMT)
committerMiguel Sofer <miguel.sofer@gmail.com>2007-11-10 16:08:08 (GMT)
commit0e7fa3edd23cef23c43109db2656ccc52978c99b (patch)
treea9e86cd8a43c61ca632591c69b5c3b042f0219ca /generic/tclBasic.c
parent9f42d64486d78ab2ab370e552ded7578ed2966c6 (diff)
downloadtcl-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.c44
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;