From 29bbca5c2c1ad41b2a9747890d183b6dd3a4ace4 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 4 Mar 2022 13:24:04 -0500 Subject: runtime: differentiate "user" and "system" throws "User" throws are throws due to some invariant broken by the application. "System" throws are due to some invariant broken by the runtime, environment, etc (i.e., not the fault of the application). This CL sends "user" throws through the new fatal. Currently this function is identical to throw, but with a different name to clearly differentiate the throw type in the stack trace, and hopefully be a bit more clear to users what it means. This CL changes a few categories of throw to fatal: 1. Concurrent map read/write. 2. Deadlock detection. 3. Unlock of unlocked sync.Mutex. 4. Inconsistent results from syscall.AllThreadsSyscall. "Thread exhaustion" and "out of memory" (usually address space full) throws are additional throws that are arguably the fault of user code, but I've left off for now because there is no specific invariant that they have broken to get into these states. For #51485 Change-Id: I713276a6c290fd34a6563e6e9ef378669d74ae32 Reviewed-on: https://go-review.googlesource.com/c/go/+/390420 TryBot-Result: Gopher Robot Reviewed-by: Austin Clements Run-TryBot: Michael Pratt --- src/sync/mutex.go | 6 ++++-- src/sync/rwmutex.go | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/sync') diff --git a/src/sync/mutex.go b/src/sync/mutex.go index 18b2cedba7..80bb827054 100644 --- a/src/sync/mutex.go +++ b/src/sync/mutex.go @@ -16,7 +16,9 @@ import ( "unsafe" ) -func throw(string) // provided by runtime +// Provided by runtime via linkname. +func throw(string) +func fatal(string) // A Mutex is a mutual exclusion lock. // The zero value for a Mutex is an unlocked mutex. @@ -217,7 +219,7 @@ func (m *Mutex) Unlock() { func (m *Mutex) unlockSlow(new int32) { if (new+mutexLocked)&mutexLocked == 0 { - throw("sync: unlock of unlocked mutex") + fatal("sync: unlock of unlocked mutex") } if new&mutexStarving == 0 { old := new diff --git a/src/sync/rwmutex.go b/src/sync/rwmutex.go index f0d4c9771a..7b10808ec4 100644 --- a/src/sync/rwmutex.go +++ b/src/sync/rwmutex.go @@ -118,7 +118,7 @@ func (rw *RWMutex) RUnlock() { func (rw *RWMutex) rUnlockSlow(r int32) { if r+1 == 0 || r+1 == -rwmutexMaxReaders { race.Enable() - throw("sync: RUnlock of unlocked RWMutex") + fatal("sync: RUnlock of unlocked RWMutex") } // A writer is pending. if atomic.AddInt32(&rw.readerWait, -1) == 0 { @@ -198,7 +198,7 @@ func (rw *RWMutex) Unlock() { r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders) if r >= rwmutexMaxReaders { race.Enable() - throw("sync: Unlock of unlocked RWMutex") + fatal("sync: Unlock of unlocked RWMutex") } // Unblock blocked readers, if any. for i := 0; i < int(r); i++ { -- cgit v1.3