From b25b5f3ff4e671aa4f5897c788137fe91f62cf57 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Tue, 27 Aug 2024 21:02:02 +0000 Subject: runtime: fix GODEBUG=gccheckmark=1 and add smoke test This change fixes GODEBUG=gccheckmark=1 which seems to have bit-rotted. Because the root jobs weren't being reset, it wasn't doing anything. Then, it turned out that checkmark mode would queue up noscan objects in workbufs, which caused it to fail. Then it turned out checkmark mode was broken with user arenas, since their heap arenas are not registered anywhere. Then, it turned out that checkmark mode could just not run properly if the goroutine's preemption flag was set (since sched.gcwaiting is true during the STW). And lastly, it turned out that async preemption could cause erroneous checkmark failures. This change fixes all these issues and adds a simple smoke test to dist to run the runtime tests under gccheckmark, which exercises all of these issues. Fixes #69074. Fixes #69377. Fixes #69376. Change-Id: Iaa0bb7b9e63ed4ba34d222b47510d6292ce168bc Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest Reviewed-on: https://go-review.googlesource.com/c/go/+/608915 LUCI-TryBot-Result: Go LUCI Auto-Submit: Michael Knyszek Reviewed-by: Carlos Amedee --- src/runtime/runtime1.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/runtime/runtime1.go') diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index b47c589075..fb16f6daef 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -440,6 +440,23 @@ func parsedebugvars() { debug.malloc = (debug.inittrace | debug.sbrk) != 0 debug.profstackdepth = min(debug.profstackdepth, maxProfStackDepth) + // Disable async preemption in checkmark mode. The following situation is + // problematic with checkmark mode: + // + // - The GC doesn't mark object A because it is truly dead. + // - The GC stops the world, asynchronously preempting G1 which has a reference + // to A in its top stack frame + // - During the stop the world, we run the second checkmark GC. It marks the roots + // and discovers A through G1. + // - Checkmark mode reports a failure since there's a discrepancy in mark metadata. + // + // We could disable just conservative scanning during the checkmark scan, which is + // safe but makes checkmark slightly less powerful, but that's a lot more invasive + // than just disabling async preemption altogether. + if debug.gccheckmark > 0 { + debug.asyncpreemptoff = 1 + } + setTraceback(gogetenv("GOTRACEBACK")) traceback_env = traceback_cache } -- cgit v1.3-5-g9baa