1diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
2--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
3+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
4@@ -1976,7 +1976,8 @@
5   // because in async signal processing case (when handler is called directly
6   // from rtl_generic_sighandler) we have not yet received the reraised
7   // signal; and it looks too fragile to intercept all ways to reraise a signal.
8-  if (flags()->report_bugs && !sync && sig != SIGTERM && errno != 99) {
9+  if (ShouldReport(thr, ReportTypeErrnoInSignal) && !sync && sig != SIGTERM &&
10+      errno != 99) {
11     VarSizeStackTrace stack;
12     // StackTrace::GetNestInstructionPc(pc) is used because return address is
13     // expected, OutputReport() will undo this.
14diff --git a/compiler-rt/lib/tsan/rtl/tsan_mman.cpp b/compiler-rt/lib/tsan/rtl/tsan_mman.cpp
15--- a/compiler-rt/lib/tsan/rtl/tsan_mman.cpp
16+++ b/compiler-rt/lib/tsan/rtl/tsan_mman.cpp
17@@ -145,7 +145,7 @@
18
19 static void SignalUnsafeCall(ThreadState *thr, uptr pc) {
20   if (atomic_load_relaxed(&thr->in_signal_handler) == 0 ||
21-      !flags()->report_signal_unsafe)
22+      !ShouldReport(thr, ReportTypeSignalUnsafe))
23     return;
24   VarSizeStackTrace stack;
25   ObtainCurrentStack(thr, pc, &stack);
26diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
27--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h
28+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h
29@@ -624,6 +624,7 @@
30   ScopedErrorReportLock lock_;
31 };
32
33+bool ShouldReport(ThreadState *thr, ReportType typ);
34 ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack);
35 void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk,
36                   MutexSet *mset, uptr *tag = nullptr);
37diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
38--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
39+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
40@@ -519,23 +519,22 @@
41 void ForkBefore(ThreadState *thr, uptr pc) {
42   ctx->thread_registry->Lock();
43   ctx->report_mtx.Lock();
44-  // Ignore memory accesses in the pthread_atfork callbacks.
45-  // If any of them triggers a data race we will deadlock
46-  // on the report_mtx.
47+  // Suppress all reports in the pthread_atfork callbacks.
48+  // Reports will deadlock on the report_mtx.
49   // We could ignore interceptors and sync operations as well,
50   // but so far it's unclear if it will do more good or harm.
51   // Unnecessarily ignoring things can lead to false positives later.
52-  ThreadIgnoreBegin(thr, pc);
53+  thr->suppress_reports++;
54 }
55
56 void ForkParentAfter(ThreadState *thr, uptr pc) {
57-  ThreadIgnoreEnd(thr, pc);  // Begin is in ForkBefore.
58+  thr->suppress_reports--;  // Enabled in ForkBefore.
59   ctx->report_mtx.Unlock();
60   ctx->thread_registry->Unlock();
61 }
62
63 void ForkChildAfter(ThreadState *thr, uptr pc) {
64-  ThreadIgnoreEnd(thr, pc);  // Begin is in ForkBefore.
65+  thr->suppress_reports--;  // Enabled in ForkBefore.
66   ctx->report_mtx.Unlock();
67   ctx->thread_registry->Unlock();
68
69diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
70--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
71+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_mutex.cpp
72@@ -51,6 +51,8 @@
73   // or false positives (e.g. unlock in a different thread).
74   if (SANITIZER_GO)
75     return;
76+  if (!ShouldReport(thr, typ))
77+    return;
78   ThreadRegistryLock l(ctx->thread_registry);
79   ScopedReport rep(typ);
80   rep.AddMutex(mid);
81@@ -107,7 +109,7 @@
82   if (!unlock_locked)
83     s->Reset(thr->proc());  // must not reset it before the report is printed
84   s->mtx.Unlock();
85-  if (unlock_locked) {
86+  if (unlock_locked && ShouldReport(thr, ReportTypeMutexDestroyLocked)) {
87     ThreadRegistryLock l(ctx->thread_registry);
88     ScopedReport rep(ReportTypeMutexDestroyLocked);
89     rep.AddMutex(mid);
90@@ -534,7 +536,7 @@
91 }
92
93 void ReportDeadlock(ThreadState *thr, uptr pc, DDReport *r) {
94-  if (r == 0)
95+  if (r == 0 || !ShouldReport(thr, ReportTypeDeadlock))
96     return;
97   ThreadRegistryLock l(ctx->thread_registry);
98   ScopedReport rep(ReportTypeDeadlock);
99diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
100--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
101+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cpp
102@@ -142,6 +142,27 @@
103   return stack;
104 }
105
106+bool ShouldReport(ThreadState *thr, ReportType typ) {
107+  // We set thr->suppress_reports in the fork context.
108+  // Taking any locking in the fork context can lead to deadlocks.
109+  // If any locks are already taken, it's too late to do this check.
110+  CheckNoLocks(thr);
111+  if (SANITIZER_DEBUG)
112+    ThreadRegistryLock l(ctx->thread_registry);
113+  if (!flags()->report_bugs || thr->suppress_reports)
114+    return false;
115+  switch (typ) {
116+    case ReportTypeSignalUnsafe:
117+      return flags()->report_signal_unsafe;
118+    case ReportTypeThreadLeak:
119+      return flags()->report_thread_leaks;
120+    case ReportTypeMutexDestroyLocked:
121+      return flags()->report_destroy_locked;
122+    default:
123+      return true;
124+  }
125+}
126+
127 ScopedReportBase::ScopedReportBase(ReportType typ, uptr tag) {
128   ctx->thread_registry->CheckLocked();
129   void *mem = internal_alloc(MBlockReport, sizeof(ReportDesc));
130@@ -497,8 +518,10 @@
131 }
132
133 bool OutputReport(ThreadState *thr, const ScopedReport &srep) {
134-  if (!flags()->report_bugs || thr->suppress_reports)
135-    return false;
136+  // These should have been checked in ShouldReport.
137+  // It's too late to check them here, we have already taken locks.
138+  CHECK(flags()->report_bugs);
139+  CHECK(!thr->suppress_reports);
140   atomic_store_relaxed(&ctx->last_symbolize_time_ns, NanoTime());
141   const ReportDesc *rep = srep.GetReport();
142   CHECK_EQ(thr->current_report, nullptr);
143@@ -589,7 +612,7 @@
144   // at best it will cause deadlocks on internal mutexes.
145   ScopedIgnoreInterceptors ignore;
146
147-  if (!flags()->report_bugs)
148+  if (!ShouldReport(thr, ReportTypeRace))
149     return;
150   if (!flags()->report_atomic_races && !RaceBetweenAtomicAndFree(thr))
151     return;
152diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp
153--- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp
154+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp
155@@ -210,7 +210,7 @@
156 void ThreadFinalize(ThreadState *thr) {
157   ThreadCheckIgnore(thr);
158 #if !SANITIZER_GO
159-  if (!flags()->report_thread_leaks)
160+  if (!ShouldReport(thr, ReportTypeThreadLeak))
161     return;
162   ThreadRegistryLock l(ctx->thread_registry);
163   Vector<ThreadLeak> leaks;
164diff --git a/compiler-rt/test/tsan/pthread_atfork_deadlock3.c b/compiler-rt/test/tsan/pthread_atfork_deadlock3.c
165new file mode 100644
166--- /dev/null
167+++ b/compiler-rt/test/tsan/pthread_atfork_deadlock3.c
168@@ -0,0 +1,71 @@
169+// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
170+// Regression test for
171+// https://groups.google.com/g/thread-sanitizer/c/TQrr4-9PRYo/m/HFR4FMi6AQAJ
172+#include "test.h"
173+#include <sys/types.h>
174+#include <sys/wait.h>
175+#include <errno.h>
176+#include <string.h>
177+#include <signal.h>
178+
179+long glob = 0;
180+
181+void *worker(void *main) {
182+  glob++;
183+  barrier_wait(&barrier);
184+  barrier_wait(&barrier);
185+  pthread_kill((pthread_t)main, SIGPROF);
186+  barrier_wait(&barrier);
187+  return NULL;
188+}
189+
190+void atfork() {
191+  barrier_wait(&barrier);
192+  barrier_wait(&barrier);
193+  write(2, "in atfork\n", strlen("in atfork\n"));
194+  static volatile long a;
195+  __atomic_fetch_add(&a, 1, __ATOMIC_RELEASE);
196+}
197+
198+void handler(int sig) {
199+  write(2, "in handler\n", strlen("in handler\n"));
200+  glob++;
201+}
202+
203+int main() {
204+  barrier_init(&barrier, 2);
205+  struct sigaction act = {};
206+  act.sa_handler = &handler;
207+  if (sigaction(SIGPROF, &act, 0)) {
208+    perror("sigaction");
209+    exit(1);
210+  }
211+  pthread_atfork(atfork, NULL, NULL);
212+  pthread_t t;
213+  pthread_create(&t, NULL, worker, (void*)pthread_self());
214+  barrier_wait(&barrier);
215+  pid_t pid = fork();
216+  if (pid < 0) {
217+    fprintf(stderr, "fork failed: %d\n", errno);
218+    return 1;
219+  }
220+  if (pid == 0) {
221+    fprintf(stderr, "CHILD\n");
222+    return 0;
223+  }
224+  if (pid != waitpid(pid, NULL, 0)) {
225+    fprintf(stderr, "waitpid failed: %d\n", errno);
226+    return 1;
227+  }
228+  pthread_join(t, NULL);
229+  fprintf(stderr, "PARENT\n");
230+  return 0;
231+}
232+
233+// CHECK: in atfork
234+// CHECK: in handler
235+// Note: There is a race, but we won't report it
236+// to not deadlock.
237+// CHECK-NOT: ThreadSanitizer: data race
238+// CHECK: CHILD
239+// CHECK: PARENT
240
241