diff options
author | Russ Cox <rsc@golang.org> | 2011-02-11 17:47:17 -0500 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2011-02-11 17:47:17 -0500 |
commit | 26880d7e034bcfd3ca45121148a3f7443409b39e (patch) | |
tree | b287f6636d4c1e912b27b805ff673da9322e07c1 | |
parent | ca5179d3f6889185f2aa3fb985f34a963015d133 (diff) | |
download | go-26880d7e034bcfd3ca45121148a3f7443409b39e.tar.gz go-26880d7e034bcfd3ca45121148a3f7443409b39e.zip |
sync: check Unlock of unlocked Mutex
R=r, adg
CC=golang-dev
https://golang.org/cl/4180044
-rw-r--r-- | src/pkg/sync/mutex.go | 7 | ||||
-rw-r--r-- | src/pkg/sync/mutex_test.go | 13 |
2 files changed, 19 insertions, 1 deletions
diff --git a/src/pkg/sync/mutex.go b/src/pkg/sync/mutex.go index 6c8a5d51d4..2a1270b9c4 100644 --- a/src/pkg/sync/mutex.go +++ b/src/pkg/sync/mutex.go @@ -53,9 +53,14 @@ func (m *Mutex) Lock() { // It is allowed for one goroutine to lock a Mutex and then // arrange for another goroutine to unlock it. func (m *Mutex) Unlock() { - if xadd(&m.key, -1) == 0 { + switch v := xadd(&m.key, -1); { + case v == 0: // changed from 1 to 0; no contention return + case int32(v) == -1: + // changed from 0 to -1: wasn't locked + // (or there are 4 billion goroutines waiting) + panic("sync: unlock of unlocked mutex") } runtime.Semrelease(&m.sema) } diff --git a/src/pkg/sync/mutex_test.go b/src/pkg/sync/mutex_test.go index d0e048ed7a..f5c20ca49b 100644 --- a/src/pkg/sync/mutex_test.go +++ b/src/pkg/sync/mutex_test.go @@ -89,3 +89,16 @@ func BenchmarkContendedMutex(b *testing.B) { <-c <-c } + +func TestMutexPanic(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatalf("unlock of unlocked mutex did not panic") + } + }() + + var mu Mutex + mu.Lock() + mu.Unlock() + mu.Unlock() +} |