From c31efeffe55db3273172e18977c0d1618870d158 Mon Sep 17 00:00:00 2001 From: Matt Goodall Date: Tue, 10 Jul 2012 17:20:16 +0100 Subject: [PATCH] Protect XMPP filters from concurrent access. --- src/xmpp/xmpp.go | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/xmpp/xmpp.go b/src/xmpp/xmpp.go index da81578..9e9cf83 100644 --- a/src/xmpp/xmpp.go +++ b/src/xmpp/xmpp.go @@ -3,6 +3,7 @@ package xmpp import ( "fmt" "log" + "sync" ) // Handles XMPP conversations over a Stream. Use NewClientXMPP and/or @@ -18,6 +19,7 @@ type XMPP struct { out chan interface{} // Incoming stanza filters. + filterLock sync.Mutex nextFilterId FilterId filters map[FilterId]filter } @@ -71,20 +73,36 @@ func (fid FilterId) Error() string { } func (x *XMPP) AddFilter(fn FilterFn) (FilterId, chan interface{}) { - ch := make(chan interface{}) + + // Protect against concurrent access. + x.filterLock.Lock() + defer x.filterLock.Lock() + + // Create filter chan and add to map. filterId := x.nextFilterId x.nextFilterId ++ + ch := make(chan interface{}) x.filters[filterId] = filter{fn, ch} + return filterId, ch } func (x *XMPP) RemoveFilter(id FilterId) error { + + // Protect against concurrent access. + x.filterLock.Lock() + defer x.filterLock.Lock() + + // Find filter. filter, ok := x.filters[id] if !ok { return id } + + // Close filter channel and remove from map. close(filter.ch) delete(x.filters, id) + return nil } @@ -157,7 +175,3 @@ func (x *XMPP) receiver() { } } } - -// BUG(matt): filter id generation is not re-entrant. - -// BUG(matt): filters map is not re-entrant.