forked from OSchip/llvm-project
Fix a deadlock in __cxa_guard_abort in tsan
hat tip: @The_Whole_Daisy for helping to isolate Reviewed By: dvyukov, fowles Differential Revision: https://reviews.llvm.org/D113713
This commit is contained in:
parent
6c8eecd676
commit
2d9bdd9dba
|
@ -880,10 +880,11 @@ static int guard_acquire(ThreadState *thr, uptr pc, atomic_uint32_t *g,
|
|||
}
|
||||
}
|
||||
|
||||
static void guard_release(ThreadState *thr, uptr pc, atomic_uint32_t *g) {
|
||||
static void guard_release(ThreadState *thr, uptr pc, atomic_uint32_t *g,
|
||||
u32 v) {
|
||||
if (!thr->in_ignored_lib)
|
||||
Release(thr, pc, (uptr)g);
|
||||
u32 old = atomic_exchange(g, kGuardDone, memory_order_release);
|
||||
u32 old = atomic_exchange(g, v, memory_order_release);
|
||||
if (old & kGuardWaiter)
|
||||
FutexWake(g, 1 << 30);
|
||||
}
|
||||
|
@ -913,12 +914,12 @@ STDCXX_INTERCEPTOR(int, __cxa_guard_acquire, atomic_uint32_t *g) {
|
|||
|
||||
STDCXX_INTERCEPTOR(void, __cxa_guard_release, atomic_uint32_t *g) {
|
||||
SCOPED_INTERCEPTOR_RAW(__cxa_guard_release, g);
|
||||
guard_release(thr, pc, g);
|
||||
guard_release(thr, pc, g, kGuardDone);
|
||||
}
|
||||
|
||||
STDCXX_INTERCEPTOR(void, __cxa_guard_abort, atomic_uint32_t *g) {
|
||||
SCOPED_INTERCEPTOR_RAW(__cxa_guard_abort, g);
|
||||
atomic_store(g, kGuardInit, memory_order_relaxed);
|
||||
guard_release(thr, pc, g, kGuardInit);
|
||||
}
|
||||
|
||||
namespace __tsan {
|
||||
|
@ -1515,7 +1516,7 @@ TSAN_INTERCEPTOR(int, pthread_once, void *o, void (*f)()) {
|
|||
// result in crashes due to too little stack space.
|
||||
if (guard_acquire(thr, pc, a, !SANITIZER_MAC)) {
|
||||
(*f)();
|
||||
guard_release(thr, pc, a);
|
||||
guard_release(thr, pc, a, kGuardDone);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct P {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
int Helper() {
|
||||
try {
|
||||
static int i = []() {
|
||||
throw P{};
|
||||
return 1;
|
||||
}();
|
||||
return i;
|
||||
} catch (P) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void *Thread(void *x) {
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
Helper();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
pthread_t t[2];
|
||||
pthread_create(&t[0], 0, Thread, 0);
|
||||
pthread_create(&t[1], 0, Thread, 0);
|
||||
pthread_join(t[0], 0);
|
||||
pthread_join(t[1], 0);
|
||||
fprintf(stderr, "PASS\n");
|
||||
}
|
||||
|
||||
// CHECK-NOT: WARNING: ThreadSanitizer: data race
|
Loading…
Reference in New Issue