Merge "Have pthread_attr_getstack for the main thread report RLIMIT_STACK..."
This commit is contained in:
commit
f4e721dd51
@ -116,6 +116,16 @@ int pthread_attr_setstack(pthread_attr_t* attr, void* stack_base, size_t stack_s
|
|||||||
static int __pthread_attr_getstack_main_thread(void** stack_base, size_t* stack_size) {
|
static int __pthread_attr_getstack_main_thread(void** stack_base, size_t* stack_size) {
|
||||||
ErrnoRestorer errno_restorer;
|
ErrnoRestorer errno_restorer;
|
||||||
|
|
||||||
|
rlimit stack_limit;
|
||||||
|
if (getrlimit(RLIMIT_STACK, &stack_limit) == -1) {
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the current RLIMIT_STACK is RLIM_INFINITY, only admit to an 8MiB stack for sanity's sake.
|
||||||
|
if (stack_limit.rlim_cur == RLIM_INFINITY) {
|
||||||
|
stack_limit.rlim_cur = 8 * 1024 * 1024;
|
||||||
|
}
|
||||||
|
|
||||||
// It doesn't matter which thread we are; we're just looking for "[stack]".
|
// It doesn't matter which thread we are; we're just looking for "[stack]".
|
||||||
FILE* fp = fopen("/proc/self/maps", "re");
|
FILE* fp = fopen("/proc/self/maps", "re");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
@ -126,17 +136,8 @@ static int __pthread_attr_getstack_main_thread(void** stack_base, size_t* stack_
|
|||||||
if (ends_with(line, " [stack]\n")) {
|
if (ends_with(line, " [stack]\n")) {
|
||||||
uintptr_t lo, hi;
|
uintptr_t lo, hi;
|
||||||
if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR, &lo, &hi) == 2) {
|
if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR, &lo, &hi) == 2) {
|
||||||
*stack_base = reinterpret_cast<void*>(lo);
|
|
||||||
*stack_size = hi - lo;
|
|
||||||
|
|
||||||
// Does our current RLIMIT_STACK mean we won't actually get everything /proc/maps promises?
|
|
||||||
rlimit stack_limit;
|
|
||||||
if (getrlimit(RLIMIT_STACK, &stack_limit) != -1) {
|
|
||||||
if (*stack_size > stack_limit.rlim_cur) {
|
|
||||||
*stack_size = stack_limit.rlim_cur;
|
*stack_size = stack_limit.rlim_cur;
|
||||||
}
|
*stack_base = reinterpret_cast<void*>(hi - *stack_size);
|
||||||
}
|
|
||||||
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -842,8 +842,7 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
|
|||||||
EXPECT_EQ(stack_size, stack_size2);
|
EXPECT_EQ(stack_size, stack_size2);
|
||||||
|
|
||||||
// What does /proc/self/maps' [stack] line say?
|
// What does /proc/self/maps' [stack] line say?
|
||||||
void* maps_stack_base = NULL;
|
void* maps_stack_hi = NULL;
|
||||||
size_t maps_stack_size = 0;
|
|
||||||
FILE* fp = fopen("/proc/self/maps", "r");
|
FILE* fp = fopen("/proc/self/maps", "r");
|
||||||
ASSERT_TRUE(fp != NULL);
|
ASSERT_TRUE(fp != NULL);
|
||||||
char line[BUFSIZ];
|
char line[BUFSIZ];
|
||||||
@ -852,31 +851,25 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
|
|||||||
char name[10];
|
char name[10];
|
||||||
sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d %10s", &lo, &hi, name);
|
sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d %10s", &lo, &hi, name);
|
||||||
if (strcmp(name, "[stack]") == 0) {
|
if (strcmp(name, "[stack]") == 0) {
|
||||||
maps_stack_base = reinterpret_cast<void*>(lo);
|
maps_stack_hi = reinterpret_cast<void*>(hi);
|
||||||
maps_stack_size = hi - lo;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
#if defined(__BIONIC__)
|
// The stack size should correspond to RLIMIT_STACK.
|
||||||
// bionic thinks that the stack base and size should correspond to the mapped region.
|
|
||||||
EXPECT_EQ(maps_stack_base, stack_base);
|
|
||||||
EXPECT_EQ(maps_stack_size, stack_size);
|
|
||||||
#else
|
|
||||||
// glibc doesn't give the true extent for some reason.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Both bionic and glibc agree that the high address you can compute from the returned
|
|
||||||
// values should match what /proc/self/maps says.
|
|
||||||
void* stack_end = reinterpret_cast<uint8_t*>(stack_base) + stack_size;
|
|
||||||
void* maps_stack_end = reinterpret_cast<uint8_t*>(maps_stack_base) + maps_stack_size;
|
|
||||||
EXPECT_EQ(maps_stack_end, stack_end);
|
|
||||||
|
|
||||||
//
|
|
||||||
// What if the rlimit is smaller than the stack's current extent?
|
|
||||||
//
|
|
||||||
rlimit rl;
|
rlimit rl;
|
||||||
|
ASSERT_EQ(0, getrlimit(RLIMIT_STACK, &rl));
|
||||||
|
EXPECT_EQ(rl.rlim_cur, stack_size);
|
||||||
|
|
||||||
|
// The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size.
|
||||||
|
// Remember that the stack grows down (and is mapped in on demand), so the low address of the
|
||||||
|
// region isn't very interesting.
|
||||||
|
EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size);
|
||||||
|
|
||||||
|
//
|
||||||
|
// What if RLIMIT_STACK is smaller than the stack's current extent?
|
||||||
|
//
|
||||||
rl.rlim_cur = rl.rlim_max = 1024; // 1KiB. We know the stack must be at least a page already.
|
rl.rlim_cur = rl.rlim_max = 1024; // 1KiB. We know the stack must be at least a page already.
|
||||||
rl.rlim_max = RLIM_INFINITY;
|
rl.rlim_max = RLIM_INFINITY;
|
||||||
ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
|
ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
|
||||||
@ -889,7 +882,7 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
|
|||||||
ASSERT_EQ(1024U, stack_size);
|
ASSERT_EQ(1024U, stack_size);
|
||||||
|
|
||||||
//
|
//
|
||||||
// What if the rlimit isn't a whole number of pages?
|
// What if RLIMIT_STACK isn't a whole number of pages?
|
||||||
//
|
//
|
||||||
rl.rlim_cur = rl.rlim_max = 6666; // Not a whole number of pages.
|
rl.rlim_cur = rl.rlim_max = 6666; // Not a whole number of pages.
|
||||||
rl.rlim_max = RLIM_INFINITY;
|
rl.rlim_max = RLIM_INFINITY;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user