Commit 733162fd authored by James Chacon's avatar James Chacon Committed by Russ Cox

runtime: prevent racefini from being invoked more than once

racefini calls __tsan_fini which is C code and at the end of it
invoked the standard C library exit(3) call. This has undefined
behavior if invoked more than once. Specifically in C++ programs
it caused static destructors to run twice. At least on glibc
impls it also means the at_exit handlers list (where those are
stored) also free's a list entry when it completes these. So invoking
twice results in a double free at exit which trips debug memory
allocation tracking.

Fix all of this by using an atomic as a boolean barrier around
calls to racefini being invoked > 1 time.

Fixes #15578

Change-Id: I49222aa9b8ded77160931f46434c61a8379570fc
Reviewed-on: https://go-review.googlesource.com/22882Reviewed-by: default avatarDmitry Vyukov <dvyukov@google.com>
Run-TryBot: Dmitry Vyukov <dvyukov@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent f744717d
......@@ -283,8 +283,16 @@ func raceinit() (gctx, pctx uintptr) {
return
}
var raceFiniLock mutex
//go:nosplit
func racefini() {
// racefini() can only be called once to avoid races.
// This eventually (via __tsan_fini) calls C.exit which has
// undefined behavior if called more than once. If the lock is
// already held it's assumed that the first caller exits the program
// so other calls can hang forever without an issue.
lock(&raceFiniLock)
racecall(&__tsan_fini, 0, 0, 0, 0)
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment