@@ -221,7 +221,7 @@ mod imp {
221
221
PTHREAD_CREATE_JOINABLE ) , 0 ) ;
222
222
223
223
// Reserve room for the red zone, the runtime's stack of last resort.
224
- let stack_size = cmp:: max ( stack, RED_ZONE + PTHREAD_STACK_MIN as uint ) ;
224
+ let stack_size = cmp:: max ( stack, RED_ZONE + __pthread_get_minstack ( & attr ) as uint ) ;
225
225
match pthread_attr_setstacksize ( & mut attr, stack_size as libc:: size_t ) {
226
226
0 => {
227
227
} ,
@@ -261,6 +261,51 @@ mod imp {
261
261
#[ cfg( not( target_os = "macos" ) , not( target_os = "android" ) ) ]
262
262
pub unsafe fn yield_now ( ) { assert_eq ! ( pthread_yield( ) , 0 ) ; }
263
263
264
+ #[ cfg( not( target_os = "linux" ) ) ]
265
+ unsafe fn __pthread_get_minstack ( _: * libc:: pthread_attr_t ) -> libc:: size_t {
266
+ libc:: PTHREAD_STACK_MIN
267
+ }
268
+
269
+ // glibc >= 2.15 has a __pthread_get_minstack() function that returns
270
+ // PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
271
+ // storage. We need that information to avoid blowing up when a small stack
272
+ // is created in an application with big thread-local storage requirements.
273
+ // See #6233 for rationale and details.
274
+ //
275
+ // Dynamically resolve the symbol for compatibility with older versions
276
+ // of glibc. Assumes that we've been dynamically linked to libpthread
277
+ // but that is currently always the case. Note that this means we take
278
+ // a dlopen/dlsym/dlclose hit for every new thread. Mitigating that by
279
+ // caching the symbol or the function's return value has its drawbacks:
280
+ //
281
+ // * Caching the symbol breaks when libpthread.so is reloaded because
282
+ // its address changes.
283
+ //
284
+ // * Caching the return value assumes that it's a fixed quantity.
285
+ // Not very future-proof and untrue in the presence of guard pages
286
+ // The reason __pthread_get_minstack() takes a *libc::pthread_attr_t
287
+ // as its argument is because it takes pthread_attr_setguardsize() into
288
+ // account.
289
+ //
290
+ // A better solution is to define __pthread_get_minstack() as a weak symbol
291
+ // but there is currently no way to express that in Rust code.
292
+ #[ cfg( target_os = "linux" ) ]
293
+ unsafe fn __pthread_get_minstack ( attr : * libc:: pthread_attr_t ) -> libc:: size_t {
294
+ use option:: None ;
295
+ use result:: { Err , Ok } ;
296
+ use unstable:: dynamic_lib;
297
+ match dynamic_lib:: DynamicLibrary :: open ( None ) {
298
+ Err ( err) => fail ! ( "DynamicLibrary::open(): {}" , err) ,
299
+ Ok ( handle) => {
300
+ match handle. symbol :: < extern "C" fn ( * libc:: pthread_attr_t ) ->
301
+ libc:: size_t > ( "__pthread_get_minstack" ) {
302
+ Err ( _) => libc:: PTHREAD_STACK_MIN ,
303
+ Ok ( __pthread_get_minstack) => __pthread_get_minstack ( attr) ,
304
+ }
305
+ }
306
+ }
307
+ }
308
+
264
309
extern {
265
310
fn pthread_create ( native : * mut libc:: pthread_t ,
266
311
attr : * libc:: pthread_attr_t ,
0 commit comments