summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--generic/tclBasic.c9
-rw-r--r--generic/tclInt.h4
-rw-r--r--unix/tclUnixInit.c10
-rw-r--r--unix/tclUnixThrd.c57
5 files changed, 72 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index bc14de6..5f1a1b1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2007-11-26 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclBasic.c:
+ * generic/tclInt.h:
+ * unix/tclUnixInit.c:
+ * unix/tclUnixThrd.c: Fix stack checking via workaround for bug in
+ glibc's pthread_attr_get_np, patch from [Bug 1815573]. Many thanks
+ to Sergei Golovan (aka Teo) for detecting the bug and helping
+ diagnose and develop the fix.
+
2007-11-24 Donal K. Fellows <dkf@users.sf.net>
* generic/tclCompCmds.c (TclCompileDictAppendCmd): Fix bug in [dict
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index bf8d8dc..0741813 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.284 2007/11/23 22:11:31 dkf Exp $
+ * RCS: @(#) $Id: tclBasic.c,v 1.285 2007/11/26 19:11:11 msofer Exp $
*/
#include "tclInt.h"
@@ -831,6 +831,13 @@ Tcl_CreateInterp(void)
Tcl_Panic(Tcl_GetString(Tcl_GetObjResult(interp)));
}
+ /*
+ * Insure that the stack checking mechanism for this interp is
+ * initialized.
+ */
+
+ TclInterpReady(interp);
+
return interp;
}
diff --git a/generic/tclInt.h b/generic/tclInt.h
index 260b36a..48e4eac 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclInt.h,v 1.352 2007/11/23 15:00:24 dkf Exp $
+ * RCS: @(#) $Id: tclInt.h,v 1.353 2007/11/26 19:11:12 msofer Exp $
*/
#ifndef _TCLINT
@@ -2621,7 +2621,7 @@ MODULE_SCOPE void * TclpThreadDataKeyGet(Tcl_ThreadDataKey *keyPtr);
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);
diff --git a/unix/tclUnixInit.c b/unix/tclUnixInit.c
index 7f725cb..3d8ac40 100644
--- a/unix/tclUnixInit.c
+++ b/unix/tclUnixInit.c
@@ -7,7 +7,7 @@
* Copyright (c) 1999 by Scriptics Corporation.
* All rights reserved.
*
- * RCS: @(#) $Id: tclUnixInit.c,v 1.80 2007/11/13 17:13:07 msofer Exp $
+ * RCS: @(#) $Id: tclUnixInit.c,v 1.81 2007/11/26 19:11:13 msofer Exp $
*/
#include "tclInt.h"
@@ -1145,13 +1145,13 @@ GetStackSize(
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;
diff --git a/unix/tclUnixThrd.c b/unix/tclUnixThrd.c
index cb206f9..491613a 100644
--- a/unix/tclUnixThrd.c
+++ b/unix/tclUnixThrd.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: tclUnixThrd.c,v 1.53 2007/11/16 11:17:28 dkf Exp $
+ * RCS: @(#) $Id: tclUnixThrd.c,v 1.54 2007/11/26 19:11:13 msofer Exp $
*/
#include "tclInt.h"
@@ -216,24 +216,61 @@ TclpThreadExit(
*----------------------------------------------------------------------
*/
-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 @@ TclpThreadGetStackSize(void)
* want to try looking at the process accounting limits instead.
*/
#endif
- return (int) stackSize;
+ return stackSize;
}
#endif /* TCL_THREADS */