]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: prevent double lock in checkdead by unlocking before throws
authorLucien Coffe <lucien.coffe@botify.com>
Fri, 21 Apr 2023 15:20:19 +0000 (17:20 +0200)
committerGopher Robot <gobot@golang.org>
Fri, 21 Apr 2023 20:14:08 +0000 (20:14 +0000)
This change resolves an issue where checkdead could result in a double lock when shedtrace is enabled. This fix involves adding unlocks before all throws in the checkdead function to ensure the scheduler lock is properly released.

Fixes #59758

Change-Id: If3ddf9969f4582c3c88dee9b9ecc355a63958103
Reviewed-on: https://go-review.googlesource.com/c/go/+/487375
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
src/runtime/proc.go

index 23d760bf84398697cd437c7fa68d08167c6c3558..fdbf888c4f635a1debc490184c1f6261ecc7cf8d 100644 (file)
@@ -5194,6 +5194,7 @@ func checkdead() {
        }
        if run < 0 {
                print("runtime: checkdead: nmidle=", sched.nmidle, " nmidlelocked=", sched.nmidlelocked, " mcount=", mcount(), " nmsys=", sched.nmsys, "\n")
+               unlock(&sched.lock)
                throw("checkdead: inconsistent counts")
        }
 
@@ -5211,6 +5212,7 @@ func checkdead() {
                        _Grunning,
                        _Gsyscall:
                        print("runtime: checkdead: find g ", gp.goid, " in status ", s, "\n")
+                       unlock(&sched.lock)
                        throw("checkdead: runnable g")
                }
        })
@@ -5229,12 +5231,14 @@ func checkdead() {
                        if pp == nil {
                                // There should always be a free P since
                                // nothing is running.
+                               unlock(&sched.lock)
                                throw("checkdead: no p for timer")
                        }
                        mp := mget()
                        if mp == nil {
                                // There should always be a free M since
                                // nothing is running.
+                               unlock(&sched.lock)
                                throw("checkdead: no m for timer")
                        }
                        // M must be spinning to steal. We set this to be