Skip to content

Commit 77ced9d

Browse files
provide workaround for pthread_get_stacksize_np
see rust-lang/rust#43347
1 parent ed9b89e commit 77ced9d

File tree

5 files changed

+115
-0
lines changed

5 files changed

+115
-0
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,11 @@ Wrapped headers and replaced functions are:
236236
<td>Adds <code>_fstatat$INODE64</code> library symbol</td>
237237
<td>OSX10.9</td>
238238
</tr>
239+
<tr>
240+
<td><code>-</code></td>
241+
<td>Provides a workaround for bug in <code>pthread_get_stacksize_np</code></td>
242+
<td>OSX10.4, OSX10.5, OSX10.9, OSX10.10</td>
243+
</tr>
239244
</table>
240245

241246
For information on building this library outside MacPorts, see BUILDING.txt.

include/MacportsLegacySupport.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,11 @@
201201
/* library symbol _dirfd */
202202
#define __MP_LEGACY_SUPPORT_SYMBOL__dirfd__ (__APPLE__ && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1080)
203203

204+
/* fix bug in pthread_get_stacksize_np */
205+
/* see https://github.com/rust-lang/rust/issues/43347 */
206+
#define __MP_LEGACY_SUPPORT_PTHREAD_GET_STACKSIZE_NP_FIX__ (__APPLE__ && ( \
207+
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ == 101000 || \
208+
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ == 1090 || \
209+
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1060 ))
210+
204211
#endif /* _MACPORTS_LEGACYSUPPORTDEFS_H_ */

src/add_symbols.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,10 @@ extern const char fstatat$INODE64_tmp7 __asm("$ld$add$os10.7$_fstatat$INODE64");
8181
extern const char fstatat$INODE64_tmp8 __asm("$ld$add$os10.8$_fstatat$INODE64"); __attribute__((visibility("default"))) const char fstatat$INODE64_tmp8 = 0;
8282
extern const char fstatat$INODE64_tmp9 __asm("$ld$add$os10.9$_fstatat$INODE64"); __attribute__((visibility("default"))) const char fstatat$INODE64_tmp9 = 0;
8383
#endif
84+
85+
#if !(__MP_LEGACY_SUPPORT_PTHREAD_GET_STACKSIZE_NP_FIX__)
86+
extern const char pthread_get_stacksize_np_tmp4 __asm("$ld$add$os10.4$_pthread_get_stacksize_np"); __attribute__((visibility("default"))) const char pthread_get_stacksize_np_tmp4 = 0;
87+
extern const char pthread_get_stacksize_np_tmp5 __asm("$ld$add$os10.5$_pthread_get_stacksize_np"); __attribute__((visibility("default"))) const char pthread_get_stacksize_np_tmp5 = 0;
88+
extern const char pthread_get_stacksize_np_tmp9 __asm("$ld$add$os10.9$_pthread_get_stacksize_np"); __attribute__((visibility("default"))) const char pthread_get_stacksize_np_tmp9 = 0;
89+
extern const char pthread_get_stacksize_np_tmp10 __asm("$ld$add$os10.10$_pthread_get_stacksize_np"); __attribute__((visibility("default"))) const char pthread_get_stacksize_np_tmp10 = 0;
90+
#endif

src/pthread_get_stacksize_np.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/* MP support header */
2+
#include "MacportsLegacySupport.h"
3+
#if __MP_LEGACY_SUPPORT_PTHREAD_GET_STACKSIZE_NP_FIX__
4+
5+
#include <pthread.h>
6+
#include <sys/resource.h>
7+
#include <dlfcn.h>
8+
#include <stdlib.h>
9+
10+
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1090
11+
/* private system call available on OS X Mavericks (version 10.9) and later */
12+
/* see https://github.com/apple-oss-distributions/libpthread/blob/ba8e1488a0e6848b710c5daad2e226f66cfed656/private/pthread/private.h#L34 */
13+
pthread_t pthread_main_thread_np(void);
14+
#endif
15+
16+
#define kMaxThreadStackSize 0x40000000 /* from LLVM: 1 << 30 or 1Gb */
17+
18+
size_t pthread_get_stacksize_np(pthread_t t) {
19+
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1090
20+
int is_main_thread = pthread_equal(t, pthread_main_thread_np());
21+
#else
22+
/* taken from Apple Libc */
23+
/* see https://github.com/apple-oss-distributions/Libc/blob/224a8105d573730ae33f474ae5b63b113123aee4/pthreads/pthread.c#L1167 */
24+
/* for _PTHREAD_CREATE_PARENT, see https://github.com/apple-oss-distributions/Libc/blob/224a8105d573730ae33f474ae5b63b113123aee4/pthreads/pthread_internals.h#L647C9-L647C31 */
25+
/* for pthread_t, see https://github.com/apple-oss-distributions/Libc/blob/224a8105d573730ae33f474ae5b63b113123aee4/pthreads/pthread_internals.h#L107 */
26+
/* for pthread_lock_t, see https://github.com/apple-oss-distributions/Libc/blob/224a8105d573730ae33f474ae5b63b113123aee4/pthreads/pthread_machdep.h#L214C13-L214C27 */
27+
struct
28+
{
29+
long sig;
30+
struct __darwin_pthread_handler_rec *cleanup_stack;
31+
int lock;
32+
__int32_t detached:8,
33+
inherit:8,
34+
policy:8,
35+
freeStackOnExit:1,
36+
newstyle:1,
37+
kernalloc:1,
38+
schedset:1,
39+
wqthread:1,
40+
pad:3;
41+
char opaque[__PTHREAD_SIZE__-sizeof(int)-sizeof(__int32_t)];
42+
} *thread = (void*) t;
43+
int is_main_thread = ((thread->detached & 4) == 4);
44+
#endif
45+
if ( is_main_thread ) {
46+
/* use LLVM workaround */
47+
/* see https://github.com/llvm/llvm-project/blob/617a15a9eac96088ae5e9134248d8236e34b91b1/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp#L414 */
48+
/* OpenJDK also has a workaround */
49+
/* see https://github.com/openjdk/jdk/blob/e833bfc8ac6104522d037e7eb300f5aa112688bb/src/hotspot/os_cpu/bsd_x86/os_bsd_x86.cpp#L715 */
50+
struct rlimit limit;
51+
if( getrlimit(RLIMIT_STACK, &limit) ) {
52+
exit(EXIT_FAILURE);
53+
}
54+
if( limit.rlim_cur < kMaxThreadStackSize ) {
55+
return limit.rlim_cur;
56+
} else {
57+
return kMaxThreadStackSize;
58+
}
59+
} else {
60+
/* bug only affects main thread */
61+
size_t (*real_pthread_get_stacksize_np)(pthread_t);
62+
real_pthread_get_stacksize_np = dlsym(RTLD_NEXT, "pthread_get_stacksize_np");
63+
if (real_pthread_get_stacksize_np == NULL) {
64+
exit(EXIT_FAILURE);
65+
}
66+
return real_pthread_get_stacksize_np(t);
67+
}
68+
}
69+
70+
#endif /* __MP_LEGACY_SUPPORT_PTHREAD_GET_STACKSIZE_NP_FIX__ */

test/test_pthread_get_stacksize_np.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <pthread.h>
2+
#include <assert.h>
3+
#include <stdio.h>
4+
#include <stddef.h>
5+
6+
#define kTooSmallStackSize 0x80000 /* from LLVM: 1 << 19, default stack size of non-main thread */
7+
8+
void *thread_function(void *arg) {
9+
assert( !pthread_main_np() && "Unknown error, thread should *not* be main." );
10+
return NULL;
11+
}
12+
13+
int main()
14+
{
15+
pthread_t thread;
16+
assert( !pthread_create(&thread, NULL, thread_function, NULL) && "Unknown error, cannot create thread" );
17+
assert( (pthread_get_stacksize_np(thread) == kTooSmallStackSize) && "Stack for non-main thread is not the default value" );
18+
printf("Stack size for non-main thread seems to be ok\n");
19+
pthread_join(thread, NULL);
20+
21+
assert( pthread_main_np() && "Unknown error, thread should be main." );
22+
assert( (pthread_get_stacksize_np(pthread_self()) > kTooSmallStackSize) && "Stack for main thread is too small" );
23+
printf("Stack size for main thread seems to be ok\n");
24+
25+
return 0;
26+
}

0 commit comments

Comments
 (0)