From 4ff45821ae4635ce806fbb8d23acd96581a50304 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 1 Nov 2019 11:06:21 -0700 Subject: [PATCH] runtime: unlock sched lock when checkdead throws due to a deadlock I was doing some testing with GODEBUG=schedtrace=1,scheddetail=1 and I noticed that the program hung after a throw with "all goroutines are asleep". This is because when doing a throw or fatal panic with schedtrace the panic code does a final schedtrace, which needs to acquire the scheduler lock. The checkdead function is always called with the scheduler lock held. So checkdead would throw with the scheduler lock held, then the panic code would call schedtrace, which would block trying to acquire the scheduler lock. This problem will only happen for people debugging the runtime, but it's easy to avoid by having checkdead unlock the scheduler lock before it throws. I only did this for the throws that can happen for a normal program, not for throws that indicate some corruption in the scheduler data. Change-Id: Ic62277b3ca6bee6f0fca8d5eb516c59cb67855cb Reviewed-on: https://go-review.googlesource.com/c/go/+/204778 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- src/runtime/proc.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/runtime/proc.go b/src/runtime/proc.go index fc8aa3330a0..f9a22ca5e3f 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4359,6 +4359,7 @@ func checkdead() { } unlock(&allglock) if grunning == 0 { // possible if main goroutine calls runtime·Goexit() + unlock(&sched.lock) // unlock so that GODEBUG=scheddetail=1 doesn't hang throw("no goroutines (main called runtime.Goexit) - deadlock!") } @@ -4411,6 +4412,7 @@ func checkdead() { } getg().m.throwing = -1 // do not dump full stacks + unlock(&sched.lock) // unlock so that GODEBUG=scheddetail=1 doesn't hang throw("all goroutines are asleep - deadlock!") }