[compiler-rt] r318707 - [tsan] Fix sigaction implementation when it's called only to get handler
Vitaly Buka via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 20 15:37:46 PST 2017
Author: vitalybuka
Date: Mon Nov 20 15:37:46 2017
New Revision: 318707
URL: http://llvm.org/viewvc/llvm-project?rev=318707&view=rev
Log:
[tsan] Fix sigaction implementation when it's called only to get handler
Reviewers: eugenis
Subscribers: kubamracek, llvm-commits, krytarowski
Differential Revision: https://reviews.llvm.org/D40272
Modified:
compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=318707&r1=318706&r2=318707&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Mon Nov 20 15:37:46 2017
@@ -2287,33 +2287,35 @@ int sigaction_impl(int sig, const __sani
SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old);
__sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
__sanitizer_sigaction old_stored;
- internal_memcpy(&old_stored, &sigactions[sig], sizeof(old_stored));
- if (act == 0) return 0;
- // Copy act into sigactions[sig].
- // Can't use struct copy, because compiler can emit call to memcpy.
- // Can't use internal_memcpy, because it copies byte-by-byte,
- // and signal handler reads the handler concurrently. It it can read
- // some bytes from old value and some bytes from new value.
- // Use volatile to prevent insertion of memcpy.
- sigactions[sig].handler =
- *(volatile __sanitizer_sighandler_ptr const *)&act->handler;
- sigactions[sig].sa_flags = *(volatile int const *)&act->sa_flags;
- internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask,
- sizeof(sigactions[sig].sa_mask));
+ if (old) internal_memcpy(&old_stored, &sigactions[sig], sizeof(old_stored));
+ __sanitizer_sigaction newact;
+ if (act) {
+ // Copy act into sigactions[sig].
+ // Can't use struct copy, because compiler can emit call to memcpy.
+ // Can't use internal_memcpy, because it copies byte-by-byte,
+ // and signal handler reads the handler concurrently. It it can read
+ // some bytes from old value and some bytes from new value.
+ // Use volatile to prevent insertion of memcpy.
+ sigactions[sig].handler =
+ *(volatile __sanitizer_sighandler_ptr const *)&act->handler;
+ sigactions[sig].sa_flags = *(volatile int const *)&act->sa_flags;
+ internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask,
+ sizeof(sigactions[sig].sa_mask));
#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
- sigactions[sig].sa_restorer = act->sa_restorer;
+ sigactions[sig].sa_restorer = act->sa_restorer;
#endif
- __sanitizer_sigaction newact;
- internal_memcpy(&newact, act, sizeof(newact));
- internal_sigfillset(&newact.sa_mask);
- if ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl) {
- if (newact.sa_flags & SA_SIGINFO)
- newact.sigaction = rtl_sigaction;
- else
- newact.handler = rtl_sighandler;
+ internal_memcpy(&newact, act, sizeof(newact));
+ internal_sigfillset(&newact.sa_mask);
+ if ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl) {
+ if (newact.sa_flags & SA_SIGINFO)
+ newact.sigaction = rtl_sigaction;
+ else
+ newact.handler = rtl_sighandler;
+ }
+ ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
+ act = &newact;
}
- ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
- int res = REAL(sigaction)(sig, &newact, old);
+ int res = REAL(sigaction)(sig, act, old);
if (res == 0 && old) {
uptr cb = (uptr)old->sigaction;
if (cb == (uptr)rtl_sigaction || cb == (uptr)rtl_sighandler) {
Modified: compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc?rev=318707&r1=318706&r2=318707&view=diff
==============================================================================
--- compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc (original)
+++ compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc Mon Nov 20 15:37:46 2017
@@ -1,4 +1,6 @@
-// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" ASAN_OPTIONS="handle_segv=0" %run %t 2>&1 | FileCheck %s
+// clang-format off
+// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" %run %t 2>&1 | FileCheck %s
+// clang-format on
// JVM uses SEGV to preempt threads. All threads do a load from a known address
// periodically. When runtime needs to preempt threads, it unmaps the page.
@@ -13,11 +15,12 @@
// "benign" SEGVs that are handled by signal handler, and ensures that
// the process survive.
+#include <assert.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
-#include <signal.h>
-#include <sys/mman.h>
#include <string.h>
+#include <sys/mman.h>
#include <unistd.h>
unsigned long page_size;
@@ -35,6 +38,12 @@ int main() {
a.sa_sigaction = handler;
a.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &a, &old);
+
+ memset(&a, 0, sizeof(a));
+ sigaction(SIGSEGV, 0, &a);
+ assert(a.sa_sigaction == handler);
+ assert(a.sa_flags & SA_SIGINFO);
+
guard = mmap(0, 3 * page_size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
guard = (char*)guard + page_size; // work around a kernel bug
for (int i = 0; i < 1000000; i++) {
More information about the llvm-commits
mailing list