am 6f08b865: am 2cf5a6f6: Merge "Revert "Improve stack overflow diagnostics.""

* commit '6f08b8659a3682b7e774af6ed68b1b613e147f1b':
  Revert "Improve stack overflow diagnostics."
This commit is contained in:
Guang Zhu 2013-07-16 20:23:42 -07:00 committed by Android Git Automerger
commit 81b7df7315
3 changed files with 33 additions and 57 deletions

View File

@ -30,16 +30,12 @@
#include "pthread_internal.h" #include "pthread_internal.h"
// Traditionally we give threads a 1MiB stack. When we started allocating per-thread #define DEFAULT_STACK_SIZE (1024 * 1024)
// alternate signal stacks to ease debugging of stack overflows, we subtracted the
// same amount we were using there from the default thread stack size. This should
// keep memory usage roughly constant.
#define DEFAULT_THREAD_STACK_SIZE ((1 * 1024 * 1024) - SIGSTKSZ)
int pthread_attr_init(pthread_attr_t* attr) { int pthread_attr_init(pthread_attr_t* attr) {
attr->flags = 0; attr->flags = 0;
attr->stack_base = NULL; attr->stack_base = NULL;
attr->stack_size = DEFAULT_THREAD_STACK_SIZE; attr->stack_size = DEFAULT_STACK_SIZE;
attr->guard_size = PAGE_SIZE; attr->guard_size = PAGE_SIZE;
attr->sched_policy = SCHED_NORMAL; attr->sched_policy = SCHED_NORMAL;
attr->sched_priority = 0; attr->sched_priority = 0;

View File

@ -62,15 +62,6 @@ void __init_tls(pthread_internal_t* thread) {
thread->tls[i] = NULL; thread->tls[i] = NULL;
} }
// Create and set an alternate signal stack.
stack_t ss;
ss.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
if (ss.ss_sp != MAP_FAILED) {
ss.ss_size = SIGSTKSZ;
ss.ss_flags = 0;
sigaltstack(&ss, NULL);
}
// Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0. // Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
thread->tls[TLS_SLOT_SELF] = thread->tls; thread->tls[TLS_SLOT_SELF] = thread->tls;
thread->tls[TLS_SLOT_THREAD_ID] = thread; thread->tls[TLS_SLOT_THREAD_ID] = thread;
@ -80,9 +71,7 @@ void __init_tls(pthread_internal_t* thread) {
__set_tls(thread->tls); __set_tls(thread->tls);
} }
// This trampoline is called from the assembly _pthread_clone function. // This trampoline is called from the assembly _pthread_clone() function.
// Our 'tls' and __pthread_clone's 'child_stack' are one and the same, just growing in
// opposite directions.
extern "C" void __thread_entry(void* (*func)(void*), void* arg, void** tls) { extern "C" void __thread_entry(void* (*func)(void*), void* arg, void** tls) {
// Wait for our creating thread to release us. This lets it have time to // Wait for our creating thread to release us. This lets it have time to
// notify gdb about this thread before we start doing anything. // notify gdb about this thread before we start doing anything.
@ -198,12 +187,8 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
thread->attr.flags |= PTHREAD_ATTR_FLAG_USER_STACK; thread->attr.flags |= PTHREAD_ATTR_FLAG_USER_STACK;
} }
// Make room for the TLS area. // Make room for TLS.
// The child stack is the same address, just growing in the opposite direction.
// At offsets >= 0, we have the TLS slots.
// At offsets < 0, we have the child stack.
void** tls = (void**)((uint8_t*)(thread->attr.stack_base) + thread->attr.stack_size - BIONIC_TLS_SLOTS * sizeof(void*)); void** tls = (void**)((uint8_t*)(thread->attr.stack_base) + thread->attr.stack_size - BIONIC_TLS_SLOTS * sizeof(void*));
void* child_stack = tls;
// Create a mutex for the thread in TLS_SLOT_SELF to wait on once it starts so we can keep // Create a mutex for the thread in TLS_SLOT_SELF to wait on once it starts so we can keep
// it from doing anything until after we notify the debugger about it // it from doing anything until after we notify the debugger about it
@ -219,7 +204,7 @@ int pthread_create(pthread_t* thread_out, pthread_attr_t const* attr,
int flags = CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM; int flags = CLONE_FILES | CLONE_FS | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM;
int tid = __pthread_clone(start_routine, child_stack, flags, arg); int tid = __pthread_clone(start_routine, tls, flags, arg);
if (tid < 0) { if (tid < 0) {
int clone_errno = errno; int clone_errno = errno;
if ((thread->attr.flags & PTHREAD_ATTR_FLAG_USER_STACK) == 0) { if ((thread->attr.flags & PTHREAD_ATTR_FLAG_USER_STACK) == 0) {

View File

@ -28,15 +28,14 @@
#include "linker.h" #include "linker.h"
#include <errno.h>
#include <signal.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/mman.h> #include <unistd.h>
#include <signal.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <errno.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <unistd.h>
extern "C" int tgkill(int tgid, int tid, int sig); extern "C" int tgkill(int tgid, int tid, int sig);
@ -110,7 +109,7 @@ static int socket_abstract_client(const char* name, int type) {
* mutex is being held, so we don't want to use any libc functions that * mutex is being held, so we don't want to use any libc functions that
* could allocate memory or hold a lock. * could allocate memory or hold a lock.
*/ */
static void log_signal_summary(int signum, const siginfo_t* info) { static void logSignalSummary(int signum, const siginfo_t* info) {
const char* signal_name; const char* signal_name;
switch (signum) { switch (signum) {
case SIGILL: signal_name = "SIGILL"; break; case SIGILL: signal_name = "SIGILL"; break;
@ -150,26 +149,26 @@ static void log_signal_summary(int signum, const siginfo_t* info) {
/* /*
* Returns true if the handler for signal "signum" has SA_SIGINFO set. * Returns true if the handler for signal "signum" has SA_SIGINFO set.
*/ */
static bool have_siginfo(int signum) { static bool haveSiginfo(int signum) {
struct sigaction old_action, new_action; struct sigaction oldact, newact;
memset(&new_action, 0, sizeof(new_action)); memset(&newact, 0, sizeof(newact));
new_action.sa_handler = SIG_DFL; newact.sa_handler = SIG_DFL;
new_action.sa_flags = SA_RESTART; newact.sa_flags = SA_RESTART;
sigemptyset(&new_action.sa_mask); sigemptyset(&newact.sa_mask);
if (sigaction(signum, &new_action, &old_action) < 0) { if (sigaction(signum, &newact, &oldact) < 0) {
__libc_format_log(ANDROID_LOG_WARN, "libc", "Failed testing for SA_SIGINFO: %s", __libc_format_log(ANDROID_LOG_WARN, "libc", "Failed testing for SA_SIGINFO: %s",
strerror(errno)); strerror(errno));
return false; return false;
} }
bool result = (old_action.sa_flags & SA_SIGINFO) != 0; bool ret = (oldact.sa_flags & SA_SIGINFO) != 0;
if (sigaction(signum, &old_action, NULL) == -1) { if (sigaction(signum, &oldact, NULL) == -1) {
__libc_format_log(ANDROID_LOG_WARN, "libc", "Restore failed in test for SA_SIGINFO: %s", __libc_format_log(ANDROID_LOG_WARN, "libc", "Restore failed in test for SA_SIGINFO: %s",
strerror(errno)); strerror(errno));
} }
return result; return ret;
} }
/* /*
@ -181,11 +180,11 @@ void debuggerd_signal_handler(int n, siginfo_t* info, void*) {
* It's possible somebody cleared the SA_SIGINFO flag, which would mean * It's possible somebody cleared the SA_SIGINFO flag, which would mean
* our "info" arg holds an undefined value. * our "info" arg holds an undefined value.
*/ */
if (!have_siginfo(n)) { if (!haveSiginfo(n)) {
info = NULL; info = NULL;
} }
log_signal_summary(n, info); logSignalSummary(n, info);
pid_t tid = gettid(); pid_t tid = gettid();
int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM); int s = socket_abstract_client(DEBUGGER_SOCKET_NAME, SOCK_STREAM);
@ -246,23 +245,19 @@ void debuggerd_signal_handler(int n, siginfo_t* info, void*) {
} }
void debuggerd_init() { void debuggerd_init() {
struct sigaction action; struct sigaction act;
memset(&action, 0, sizeof(action)); memset(&act, 0, sizeof(act));
sigemptyset(&action.sa_mask); act.sa_sigaction = debuggerd_signal_handler;
action.sa_sigaction = debuggerd_signal_handler; act.sa_flags = SA_RESTART | SA_SIGINFO;
action.sa_flags = SA_RESTART | SA_SIGINFO; sigemptyset(&act.sa_mask);
// Use the alternate signal stack if available so we can catch stack overflows. sigaction(SIGILL, &act, NULL);
action.sa_flags |= SA_ONSTACK; sigaction(SIGABRT, &act, NULL);
sigaction(SIGBUS, &act, NULL);
sigaction(SIGABRT, &action, NULL); sigaction(SIGFPE, &act, NULL);
sigaction(SIGBUS, &action, NULL); sigaction(SIGSEGV, &act, NULL);
sigaction(SIGFPE, &action, NULL);
sigaction(SIGILL, &action, NULL);
sigaction(SIGPIPE, &action, NULL);
sigaction(SIGSEGV, &action, NULL);
#if defined(SIGSTKFLT) #if defined(SIGSTKFLT)
sigaction(SIGSTKFLT, &action, NULL); sigaction(SIGSTKFLT, &act, NULL);
#endif #endif
sigaction(SIGTRAP, &action, NULL); sigaction(SIGPIPE, &act, NULL);
} }