tsan: intercept _exit so that we can override exit status

llvm-svn: 191898
This commit is contained in:
Dmitry Vyukov 2013-10-03 14:00:46 +00:00
parent 5ba736457c
commit e07dc7d1fe
4 changed files with 25 additions and 10 deletions

View File

@ -75,6 +75,9 @@ struct Flags {
int flush_memory_ms; int flush_memory_ms;
// Flush symbolizer caches every X ms. // Flush symbolizer caches every X ms.
int flush_symbolizer_ms; int flush_symbolizer_ms;
// Resident memory limit in MB to aim at.
// If the process consumes more memory, then TSan will flush shadow memory.
int memory_limit_mb;
// Stops on start until __tsan_resume() is called (for debugging). // Stops on start until __tsan_resume() is called (for debugging).
bool stop_on_start; bool stop_on_start;
// Controls whether RunningOnValgrind() returns true or false. // Controls whether RunningOnValgrind() returns true or false.

View File

@ -1958,8 +1958,27 @@ static void syscall_post_fork(uptr pc, int res) {
syscall_post_fork(GET_CALLER_PC(), res) syscall_post_fork(GET_CALLER_PC(), res)
#include "sanitizer_common/sanitizer_common_syscalls.inc" #include "sanitizer_common/sanitizer_common_syscalls.inc"
TSAN_INTERCEPTOR(void, _exit, int status) {
ThreadState * thr = cur_thread();
int status1 = Finalize(thr);
REAL(fflush)(0);
if (status == 0)
status = status1;
REAL(_exit)(status);
}
namespace __tsan { namespace __tsan {
static void finalize(void *arg) {
ThreadState * thr = cur_thread();
uptr pc = 0;
atexit_ctx->exit(thr, pc);
int status = Finalize(thr);
REAL(fflush)(0);
if (status)
REAL(_exit)(status);
}
void ProcessPendingSignals(ThreadState *thr) { void ProcessPendingSignals(ThreadState *thr) {
CHECK_EQ(thr->in_rtl, 0); CHECK_EQ(thr->in_rtl, 0);
SignalContext *sctx = SigCtx(thr); SignalContext *sctx = SigCtx(thr);
@ -2009,16 +2028,6 @@ void ProcessPendingSignals(ThreadState *thr) {
thr->in_signal_handler = false; thr->in_signal_handler = false;
} }
static void finalize(void *arg) {
ThreadState * thr = cur_thread();
uptr pc = 0;
atexit_ctx->exit(thr, pc);
int status = Finalize(cur_thread());
REAL(fflush)(0);
if (status)
_exit(status);
}
static void unreachable() { static void unreachable() {
Printf("FATAL: ThreadSanitizer: unreachable called\n"); Printf("FATAL: ThreadSanitizer: unreachable called\n");
Die(); Die();
@ -2199,6 +2208,7 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(dlclose); TSAN_INTERCEPT(dlclose);
TSAN_INTERCEPT(on_exit); TSAN_INTERCEPT(on_exit);
TSAN_INTERCEPT(__cxa_atexit); TSAN_INTERCEPT(__cxa_atexit);
TSAN_INTERCEPT(_exit);
// Need to setup it, because interceptors check that the function is resolved. // Need to setup it, because interceptors check that the function is resolved.
// But atexit is emitted directly into the module, so can't be resolved. // But atexit is emitted directly into the module, so can't be resolved.

View File

@ -142,6 +142,7 @@ void StatOutput(u64 *stat) {
name[StatInt_strcasecmp] = " strcasecmp "; name[StatInt_strcasecmp] = " strcasecmp ";
name[StatInt_strncasecmp] = " strncasecmp "; name[StatInt_strncasecmp] = " strncasecmp ";
name[StatInt_atexit] = " atexit "; name[StatInt_atexit] = " atexit ";
name[StatInt__exit] = " _exit ";
name[StatInt___cxa_guard_acquire] = " __cxa_guard_acquire "; name[StatInt___cxa_guard_acquire] = " __cxa_guard_acquire ";
name[StatInt___cxa_guard_release] = " __cxa_guard_release "; name[StatInt___cxa_guard_release] = " __cxa_guard_release ";
name[StatInt___cxa_guard_abort] = " __cxa_guard_abort "; name[StatInt___cxa_guard_abort] = " __cxa_guard_abort ";

View File

@ -139,6 +139,7 @@ enum StatType {
StatInt_strstr, StatInt_strstr,
StatInt_strdup, StatInt_strdup,
StatInt_atexit, StatInt_atexit,
StatInt__exit,
StatInt___cxa_guard_acquire, StatInt___cxa_guard_acquire,
StatInt___cxa_guard_release, StatInt___cxa_guard_release,
StatInt___cxa_guard_abort, StatInt___cxa_guard_abort,