Attachment "stack.patch" to
ticket [1815573fff]
added by
msofer
2007-11-26 20:49:03.
Index: generic/tclBasic.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclBasic.c,v
retrieving revision 1.284
diff -u -r1.284 tclBasic.c
--- generic/tclBasic.c 23 Nov 2007 22:11:31 -0000 1.284
+++ generic/tclBasic.c 26 Nov 2007 13:45:58 -0000
@@ -831,6 +831,13 @@
Tcl_Panic(Tcl_GetString(Tcl_GetObjResult(interp)));
}
+ /*
+ * Insure that the stack checking mechanism for this interp is
+ * initialized.
+ */
+
+ TclInterpReady(interp);
+
return interp;
}
Index: generic/tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.352
diff -u -r1.352 tclInt.h
--- generic/tclInt.h 23 Nov 2007 15:00:24 -0000 1.352
+++ generic/tclInt.h 26 Nov 2007 13:45:58 -0000
@@ -2621,7 +2621,7 @@
MODULE_SCOPE void TclpThreadDataKeySet(Tcl_ThreadDataKey *keyPtr,
void *data);
MODULE_SCOPE void TclpThreadExit(int status);
-MODULE_SCOPE int TclpThreadGetStackSize(void);
+MODULE_SCOPE size_t TclpThreadGetStackSize(void);
MODULE_SCOPE void TclRememberCondition(Tcl_Condition *mutex);
MODULE_SCOPE void TclRememberJoinableThread(Tcl_ThreadId id);
MODULE_SCOPE void TclRememberMutex(Tcl_Mutex *mutex);
Index: unix/tclUnixInit.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclUnixInit.c,v
retrieving revision 1.80
diff -u -r1.80 tclUnixInit.c
--- unix/tclUnixInit.c 13 Nov 2007 17:13:07 -0000 1.80
+++ unix/tclUnixInit.c 26 Nov 2007 13:45:58 -0000
@@ -1145,13 +1145,13 @@
struct rlimit rLimit; /* The result from getrlimit(). */
#ifdef TCL_THREADS
- rawStackSize = (size_t) TclpThreadGetStackSize();
+ rawStackSize = TclpThreadGetStackSize();
if (rawStackSize == (size_t) -1) {
/*
- * Some kind of confirmed error?!
+ * Some kind of confirmed error in TclpThreadGetStackSize?! Fall back
+ * to whatever getrlimit can determine.
*/
- STACK_DEBUG(("skipping stack checks with failure\n"));
- return TCL_BREAK;
+ STACK_DEBUG(("stack checks: TclpThreadGetStackSize failed in \n"));
}
if (rawStackSize > 0) {
goto finalSanityCheck;
Index: unix/tclUnixThrd.c
===================================================================
RCS file: /cvsroot/tcl/tcl/unix/tclUnixThrd.c,v
retrieving revision 1.53
diff -u -r1.53 tclUnixThrd.c
--- unix/tclUnixThrd.c 16 Nov 2007 11:17:28 -0000 1.53
+++ unix/tclUnixThrd.c 26 Nov 2007 13:45:58 -0000
@@ -216,24 +216,61 @@
*----------------------------------------------------------------------
*/
-int
+size_t
TclpThreadGetStackSize(void)
{
size_t stackSize = 0;
#if defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && defined(TclpPthreadGetAttrs)
pthread_attr_t threadAttr; /* This will hold the thread attributes for
* the current thread. */
+ static int initialized = 0;
- if (pthread_attr_init(&threadAttr) != 0) {
- return -1;
- }
- if (TclpPthreadGetAttrs(pthread_self(), &threadAttr) != 0) {
- pthread_attr_destroy(&threadAttr);
- return -1;
+ /*
+ * Fix for [Bug 1815573]
+ *
+ * DESCRIPTION:
+ * On linux TclpPthreadGetAttrs (which is pthread_attr_get_np) may return
+ * bogus values on the initial thread. We have a choice: either use the
+ * default thread stack (first branch in the #if below), or return 0 and
+ * let getrlimit do its thing.
+ *
+ * ASSUMPTIONS:
+ * There seems to be no api to determine if we are on the initial
+ * thread. The simple scheme implemented here assumes:
+ * 1. The first Tcl interp to be created lives in the initial thread. If
+ * this assumption is not true, the fix is to call
+ * TclpThreadGetStackSize from the initial thread previous to
+ * creating any Tcl interpreter. In this case, especially if another
+ * Tcl interpreter may be created in the initial thread, it might be
+ * better to enable the second branch in the #if below
+ * 2. There will be no races in creating the first Tcl interp - ie, the
+ * second Tcl interp will be created only after the first call to
+ * Tcl_CreateInterp returns.
+ *
+ * These assumptions are satisfied by tclsh. Embedders may want to check
+ * their validity, and possibly adapt the code on failing to meet them.
+ */
+
+ if (!initialized) {
+ initialized = 1;
+#if 0
+ if (pthread_attr_init(&threadAttr) != 0) {
+ return 0;
+ }
+#else
+ return 0;
+#endif
+ } else {
+ if (TclpPthreadGetAttrs(pthread_self(), &threadAttr) != 0) {
+ pthread_attr_destroy(&threadAttr);
+ return (size_t)-1;
+ }
}
+
+
if (pthread_attr_getstacksize(&threadAttr, &stackSize) != 0) {
pthread_attr_destroy(&threadAttr);
- return -1;
+ return (size_t)-1;
}
pthread_attr_destroy(&threadAttr);
#elif defined(HAVE_PTHREAD_GET_STACKSIZE_NP)
@@ -251,7 +288,7 @@
* want to try looking at the process accounting limits instead.
*/
#endif
- return (int) stackSize;
+ return stackSize;
}
#endif /* TCL_THREADS */