]> Cypherpunks repositories - gostls13.git/commitdiff
sync: check Unlock of unlocked Mutex
authorRuss Cox <rsc@golang.org>
Fri, 11 Feb 2011 22:47:17 +0000 (17:47 -0500)
committerRuss Cox <rsc@golang.org>
Fri, 11 Feb 2011 22:47:17 +0000 (17:47 -0500)
R=r, adg
CC=golang-dev
https://golang.org/cl/4180044

src/pkg/sync/mutex.go
src/pkg/sync/mutex_test.go

index 6c8a5d51d42c3db298f859ba8140a3b0a1d42bed..2a1270b9c40e8d34615cbba29e00f38eb0458154 100644 (file)
@@ -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)
 }
index d0e048ed7a4a4e5351a8e61bc4c9f598169defe0..f5c20ca49b40fc367de65b6b612b4d526949b06e 100644 (file)
@@ -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()
+}