diff options
author | Miguel Sofer <miguel.sofer@gmail.com> | 2007-11-26 19:11:10 (GMT) |
---|---|---|
committer | Miguel Sofer <miguel.sofer@gmail.com> | 2007-11-26 19:11:10 (GMT) |
commit | 5b704020810cc6cd47e7e04537036e7e2c3fdf37 (patch) | |
tree | 6b66f0c497cf01b947a8bf6dcf4d6470bf62e40d /unix | |
parent | ce1010952e733cc42cf091dcfa28c2ad3dc14a9b (diff) | |
download | tcl-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.c | 10 | ||||
-rw-r--r-- | unix/tclUnixThrd.c | 57 |
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 */ |