diff --git a/event/event.go b/event/event.go index d11a0e9bdb..540fbba65a 100644 --- a/event/event.go +++ b/event/event.go @@ -3,6 +3,7 @@ package event import ( "errors" + "fmt" "reflect" "sync" ) @@ -40,6 +41,7 @@ var ErrMuxClosed = errors.New("event: mux closed") func (mux *TypeMux) Subscribe(types ...interface{}) Subscription { sub := newsub(mux) mux.mutex.Lock() + defer mux.mutex.Unlock() if mux.stopped { close(sub.postC) } else { @@ -49,13 +51,15 @@ func (mux *TypeMux) Subscribe(types ...interface{}) Subscription { for _, t := range types { rtyp := reflect.TypeOf(t) oldsubs := mux.subm[rtyp] + if find(oldsubs, sub) != -1 { + panic(fmt.Sprintf("event: duplicate type %s in Subscribe", rtyp)) + } subs := make([]*muxsub, len(oldsubs)+1) copy(subs, oldsubs) subs[len(oldsubs)] = sub mux.subm[rtyp] = subs } } - mux.mutex.Unlock() return sub } diff --git a/event/event_test.go b/event/event_test.go index f65aaa0a21..c7c0266c1a 100644 --- a/event/event_test.go +++ b/event/event_test.go @@ -60,6 +60,21 @@ func TestUnsubscribeUnblockPost(t *testing.T) { } } +func TestSubscribeDuplicateType(t *testing.T) { + mux := new(TypeMux) + expected := "event: duplicate type event.testEvent in Subscribe" + + defer func() { + err := recover() + if err == nil { + t.Errorf("Subscribe didn't panic for duplicate type") + } else if err != expected { + t.Errorf("panic mismatch: got %#v, expected %#v", err, expected) + } + }() + mux.Subscribe(testEvent(1), testEvent(2)) +} + func TestMuxConcurrent(t *testing.T) { rand.Seed(time.Now().Unix()) mux := new(TypeMux)