tsan: fix huge stack frames

llvm-svn: 177255
This commit is contained in:
Dmitry Vyukov 2013-03-18 08:09:42 +00:00
parent bd016bb614
commit 6f7ca81cce
1 changed files with 13 additions and 8 deletions

View File

@ -28,6 +28,7 @@
#include "sanitizer_libc.h" #include "sanitizer_libc.h"
#include "sanitizer_linux.h" #include "sanitizer_linux.h"
#include "sanitizer_mutex.h" #include "sanitizer_mutex.h"
#include "sanitizer_placement_new.h"
// This module works by spawning a Linux task which then attaches to every // This module works by spawning a Linux task which then attaches to every
// thread in the caller process with ptrace. This suspends the threads, and // thread in the caller process with ptrace. This suspends the threads, and
@ -140,24 +141,27 @@ void ThreadSuspender::KillAllThreads() {
} }
bool ThreadSuspender::SuspendAllThreads() { bool ThreadSuspender::SuspendAllThreads() {
ThreadLister thread_lister(pid_); void *mem = InternalAlloc(sizeof(ThreadLister));
ThreadLister *thread_lister = new(mem) ThreadLister(pid_);
bool added_threads; bool added_threads;
do { do {
// Run through the directory entries once. // Run through the directory entries once.
added_threads = false; added_threads = false;
pid_t tid = thread_lister.GetNextTID(); pid_t tid = thread_lister->GetNextTID();
while (tid >= 0) { while (tid >= 0) {
if (SuspendThread(tid)) if (SuspendThread(tid))
added_threads = true; added_threads = true;
tid = thread_lister.GetNextTID(); tid = thread_lister->GetNextTID();
} }
if (thread_lister.error()) { if (thread_lister->error()) {
// Detach threads and fail. // Detach threads and fail.
ResumeAllThreads(); ResumeAllThreads();
InternalFree(mem);
return false; return false;
} }
thread_lister.Reset(); thread_lister->Reset();
} while (added_threads); } while (added_threads);
InternalFree(mem);
return true; return true;
} }
@ -241,15 +245,17 @@ static int TracerThread(void* argument) {
return exit_code; return exit_code;
} }
static sigset_t blocked_sigset;
static sigset_t old_sigset;
static struct sigaction old_sigactions[ARRAY_SIZE(kUnblockedSignals)];
void StopTheWorld(StopTheWorldCallback callback, void *argument) { void StopTheWorld(StopTheWorldCallback callback, void *argument) {
// Block all signals that can be blocked safely, and install default handlers // Block all signals that can be blocked safely, and install default handlers
// for the remaining signals. // for the remaining signals.
// We cannot allow user-defined handlers to run while the ThreadSuspender // We cannot allow user-defined handlers to run while the ThreadSuspender
// thread is active, because they could conceivably call some libc functions // thread is active, because they could conceivably call some libc functions
// which modify errno (which is shared between the two threads). // which modify errno (which is shared between the two threads).
sigset_t blocked_sigset;
sigfillset(&blocked_sigset); sigfillset(&blocked_sigset);
struct sigaction old_sigactions[ARRAY_SIZE(kUnblockedSignals)];
for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals); for (uptr signal_index = 0; signal_index < ARRAY_SIZE(kUnblockedSignals);
signal_index++) { signal_index++) {
// Remove the signal from the set of blocked signals. // Remove the signal from the set of blocked signals.
@ -262,7 +268,6 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) {
sigaction(kUnblockedSignals[signal_index], &new_sigaction, sigaction(kUnblockedSignals[signal_index], &new_sigaction,
&old_sigactions[signal_index]); &old_sigactions[signal_index]);
} }
sigset_t old_sigset;
int sigprocmask_status = sigprocmask(SIG_BLOCK, &blocked_sigset, &old_sigset); int sigprocmask_status = sigprocmask(SIG_BLOCK, &blocked_sigset, &old_sigset);
CHECK_EQ(sigprocmask_status, 0); // sigprocmask should never fail CHECK_EQ(sigprocmask_status, 0); // sigprocmask should never fail
// Make this process dumpable. Processes that are not dumpable cannot be // Make this process dumpable. Processes that are not dumpable cannot be