summaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
authorMiguel Sofer <miguel.sofer@gmail.com>2007-11-26 19:11:10 (GMT)
committerMiguel Sofer <miguel.sofer@gmail.com>2007-11-26 19:11:10 (GMT)
commit5b704020810cc6cd47e7e04537036e7e2c3fdf37 (patch)
tree6b66f0c497cf01b947a8bf6dcf4d6470bf62e40d /unix
parentce1010952e733cc42cf091dcfa28c2ad3dc14a9b (diff)
downloadtcl-5b704020810cc6cd47e7e04537036e7e2c3fdf37.zip
tcl-5b704020810cc6cd47e7e04537036e7e2c3fdf37.tar.gz
tcl-5b704020810cc6cd47e7e04537036e7e2c3fdf37.tar.bz2
* 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.
Diffstat (limited to 'unix')
-rw-r--r--unix/tclUnixInit.c10
-rw-r--r--unix/tclUnixThrd.c57
2 files changed, 52 insertions, 15 deletions
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 */