tsan: fix leak of ThreadSignalContext for fibers
authorDmitry Vyukov <dvyukov@google.com>
Wed, 25 Mar 2020 16:03:29 +0000 (17:03 +0100)
committerDmitry Vyukov <dvyukov@google.com>
Wed, 25 Mar 2020 16:05:46 +0000 (17:05 +0100)
commitd8a0f76de7bd98dc7a271bc15b39a4cdbfdf6ecb
treef21549b1ef2edb5adbfc50fe697103cff76bd7bb
parent5f149ef51fcf08d52dd0977d54e7b3e4f15bede7
tsan: fix leak of ThreadSignalContext for fibers

When creating and destroying fibers in tsan a thread state
is created and destroyed. Currently, a memory mapping is
leaked with each fiber (in __tsan_destroy_fiber).
This causes applications with many short running fibers
to crash or hang because of linux vm.max_map_count.

The root of this is that ThreadState holds a pointer to
ThreadSignalContext for handling signals. The initialization
and destruction of it is tied to platform specific events
in tsan_interceptors_posix and missed when destroying a fiber
(specifically, SigCtx is used to lazily create the
ThreadSignalContext in tsan_interceptors_posix). This patch
cleans up the memory by inverting the control from the
platform specific code calling the generic ThreadFinish to
ThreadFinish calling a platform specific clean-up routine
after finishing a thread.

The relevant code causing the leak with fibers is the fiber destruction:

void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber) {
  FiberSwitchImpl(thr, fiber);
  ThreadFinish(fiber);
  FiberSwitchImpl(fiber, thr);
  internal_free(fiber);
}

I would appreciate feedback if this way of fixing the leak is ok.
Also, I think it would be worthwhile to more closely look at the
lifecycle of ThreadState (i.e. it uses no constructor/destructor,
thus requiring manual callbacks for cleanup) and how OS-Threads/user
level fibers are differentiated in the codebase. I would be happy to
contribute more if someone could point me at the right place to
discuss this issue.

Reviewed-in: https://reviews.llvm.org/D76073
Author: Florian (Florian)
compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
compiler-rt/lib/tsan/rtl/tsan_platform.h
compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
compiler-rt/lib/tsan/rtl/tsan_platform_mac.cpp
compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cpp
compiler-rt/test/tsan/fiber_cleanup.cpp [new file with mode: 0644]