forked from OSchip/llvm-project
[sanitizer] deadlock detector: a) initial support for suppressions, b) be more robust in case we failed to extract a stack trace for one of the locks
llvm-svn: 204225
This commit is contained in:
parent
e7e8b26f93
commit
2ea796e05f
|
@ -20,8 +20,8 @@
|
|||
namespace __sanitizer {
|
||||
|
||||
static const char *const kTypeStrings[SuppressionTypeCount] = {
|
||||
"none", "race", "mutex", "thread", "signal", "leak", "called_from_lib"
|
||||
};
|
||||
"none", "race", "mutex", "thread",
|
||||
"signal", "leak", "called_from_lib", "deadlock"};
|
||||
|
||||
bool TemplateMatch(char *templ, const char *str) {
|
||||
if (str == 0 || str[0] == 0)
|
||||
|
|
|
@ -26,6 +26,7 @@ enum SuppressionType {
|
|||
SuppressionSignal,
|
||||
SuppressionLeak,
|
||||
SuppressionLib,
|
||||
SuppressionDeadlock,
|
||||
SuppressionTypeCount
|
||||
};
|
||||
|
||||
|
|
|
@ -67,8 +67,10 @@ TEST(Suppressions, TypeStrings) {
|
|||
CHECK(!internal_strcmp(SuppressionTypeString(SuppressionLeak), "leak"));
|
||||
CHECK(!internal_strcmp(SuppressionTypeString(SuppressionLib),
|
||||
"called_from_lib"));
|
||||
CHECK(
|
||||
!internal_strcmp(SuppressionTypeString(SuppressionDeadlock), "deadlock"));
|
||||
// Ensure this test is up-to-date when suppression types are added.
|
||||
CHECK_EQ(SuppressionTypeCount, 7);
|
||||
CHECK_EQ(SuppressionTypeCount, 8);
|
||||
}
|
||||
|
||||
class SuppressionContextTest : public ::testing::Test {
|
||||
|
|
|
@ -428,17 +428,25 @@ void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
|
|||
for (int i = 0; i < r->n; i++)
|
||||
rep.AddMutex(r->loop[i].mtx_ctx0);
|
||||
StackTrace stacks[2 * DDReport::kMaxLoopSize];
|
||||
uptr dummy_pc = 0x42;
|
||||
for (int i = 0; i < r->n; i++) {
|
||||
uptr size;
|
||||
for (int j = 0; j < 2; j++) {
|
||||
u32 stk = r->loop[i].stk[j];
|
||||
if (!stk) continue;
|
||||
const uptr *trace = StackDepotGet(stk, &size);
|
||||
stacks[i].Init(const_cast<uptr *>(trace), size);
|
||||
if (stk) {
|
||||
const uptr *trace = StackDepotGet(stk, &size);
|
||||
stacks[i].Init(const_cast<uptr *>(trace), size);
|
||||
} else {
|
||||
// Sometimes we fail to extract the stack trace (FIXME: investigate),
|
||||
// but we should still produce some stack trace in the report.
|
||||
stacks[i].Init(&dummy_pc, 1);
|
||||
}
|
||||
rep.AddStack(&stacks[i]);
|
||||
}
|
||||
}
|
||||
OutputReport(ctx, rep);
|
||||
// FIXME: use all stacks for suppressions, not just the second stack of the
|
||||
// first edge.
|
||||
OutputReport(ctx, rep, rep.GetReport()->stacks[1]);
|
||||
#endif // TSAN_GO
|
||||
}
|
||||
|
||||
|
|
|
@ -107,6 +107,8 @@ SuppressionType conv(ReportType typ) {
|
|||
return SuppressionSignal;
|
||||
else if (typ == ReportTypeErrnoInSignal)
|
||||
return SuppressionNone;
|
||||
else if (typ == ReportTypeDeadlock)
|
||||
return SuppressionDeadlock;
|
||||
Printf("ThreadSanitizer: unknown report type %d\n", typ),
|
||||
Die();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
// RUN: %clangxx_tsan %s -o %t
|
||||
// RUN: TSAN_OPTIONS=detect_deadlocks=1 not %t 2>&1 | FileCheck %s
|
||||
// RUN: echo "deadlock:main" > sup
|
||||
// RUN: TSAN_OPTIONS="detect_deadlocks=1 suppressions=sup" %t
|
||||
// RUN: echo "deadlock:zzzz" > sup
|
||||
// RUN: TSAN_OPTIONS="detect_deadlocks=1 suppressions=sup" not %t 2>&1 | FileCheck %s
|
||||
#include <pthread.h>
|
||||
|
||||
int main() {
|
||||
|
|
Loading…
Reference in New Issue