summaryrefslogtreecommitdiff
path: root/lib/lsan
diff options
context:
space:
mode:
authorMaxim Ostapenko <chefmax7@gmail.com>2017-05-31 07:28:09 +0000
committerMaxim Ostapenko <chefmax7@gmail.com>2017-05-31 07:28:09 +0000
commite1a8ef98132e737d3e7c4045a3e6e6e7ae20242e (patch)
treedb489cef503c1af92ec3a9d7651d282575f9ff29 /lib/lsan
parent97fc005f646a7ce2ee15b97bb7e015a812eb2421 (diff)
[sanitizer] Avoid possible deadlock in child process after fork
This patch addresses https://github.com/google/sanitizers/issues/774. When we fork a multi-threaded process it's possible to deadlock if some thread acquired StackDepot or allocator internal lock just before fork. In this case the lock will never be released in child process causing deadlock on following memory alloc/dealloc routine. While calling alloc/dealloc routines after multi-threaded fork is not allowed, most of modern allocators (Glibc, tcmalloc, jemalloc) are actually fork safe. Let's do the same for sanitizers except TSan that has complex locking rules. Differential Revision: https://reviews.llvm.org/D33325 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@304285 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/lsan')
-rw-r--r--lib/lsan/lsan_interceptors.cc20
1 files changed, 20 insertions, 0 deletions
diff --git a/lib/lsan/lsan_interceptors.cc b/lib/lsan/lsan_interceptors.cc
index 9e39a7d19..b8cf6ae07 100644
--- a/lib/lsan/lsan_interceptors.cc
+++ b/lib/lsan/lsan_interceptors.cc
@@ -22,6 +22,7 @@
#include "sanitizer_common/sanitizer_platform_interceptors.h"
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
#include "sanitizer_common/sanitizer_posix.h"
+#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_tls_get_addr.h"
#include "lsan.h"
#include "lsan_allocator.h"
@@ -97,6 +98,24 @@ INTERCEPTOR(void*, valloc, uptr size) {
}
#endif
+static void BeforeFork() {
+ LockAllocator();
+ StackDepotLockAll();
+}
+
+static void AfterFork() {
+ StackDepotUnlockAll();
+ UnlockAllocator();
+}
+
+INTERCEPTOR(int, fork, void) {
+ ENSURE_LSAN_INITED;
+ BeforeFork();
+ int pid = REAL(fork)();
+ AfterFork();
+ return pid;
+}
+
#if SANITIZER_INTERCEPT_MEMALIGN
INTERCEPTOR(void*, memalign, uptr alignment, uptr size) {
ENSURE_LSAN_INITED;
@@ -336,6 +355,7 @@ void InitializeInterceptors() {
LSAN_MAYBE_INTERCEPT_MALLOPT;
INTERCEPT_FUNCTION(pthread_create);
INTERCEPT_FUNCTION(pthread_join);
+ INTERCEPT_FUNCTION(fork);
if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) {
Report("LeakSanitizer: failed to create thread key.\n");