@@ -57,7 +57,7 @@ type memberlist struct {
5757 // could use members lock for that, but that introduces more deadlocks, so
5858 // making a short-term fix instead by adding another lock. Like said, this
5959 // is short-term, see github#113.
60- sync.RWMutex
60+ updateLock sync.Mutex
6161}
6262
6363// newMemberlist returns a new member list
@@ -84,10 +84,8 @@ func newMemberlist(n *Node, initialLabels LabelMap) *memberlist {
8484
8585func (m * memberlist ) Checksum () uint32 {
8686 m .members .Lock ()
87- checksum := m .members .checksum
88- m .members .Unlock ()
89-
90- return checksum
87+ defer m .members .Unlock ()
88+ return m .members .checksum
9189}
9290
9391// computes membership checksum
@@ -114,6 +112,7 @@ func (m *memberlist) ComputeChecksum() {
114112}
115113
116114// generates string to use when computing checksum
115+ // call with m.members.lock
117116func (m * memberlist ) genChecksumString () string {
118117 var strings sort.StringSlice
119118 var buffer bytes.Buffer
@@ -142,7 +141,7 @@ func (m *memberlist) genChecksumString() string {
142141 return buffer .String ()
143142}
144143
145- // returns the member at a specific address
144+ // returns a copy of the member at a specific address
146145func (m * memberlist ) Member (address string ) (* Member , bool ) {
147146 var memberCopy * Member
148147 m .members .RLock ()
@@ -190,21 +189,22 @@ func (m *memberlist) RemoveMember(address string) bool {
190189 return hasMember
191190}
192191
192+ // returns a copy of the member at an index, or nil if i >= length
193193func (m * memberlist ) MemberAt (i int ) * Member {
194194 m .members .RLock ()
195+ defer m .members .RUnlock ()
196+ if i >= len (m .members .list ) {
197+ return nil
198+ }
195199 member := new (Member )
196200 * member = * m .members .list [i ]
197- m .members .RUnlock ()
198-
199201 return member
200202}
201203
202204func (m * memberlist ) NumMembers () int {
203205 m .members .RLock ()
204- n := len (m .members .list )
205- m .members .RUnlock ()
206-
207- return n
206+ defer m .members .RUnlock ()
207+ return len (m .members .list )
208208}
209209
210210// returns whether or not a member is pingable
@@ -217,12 +217,12 @@ func (m *memberlist) Pingable(member Member) bool {
217217// returns the number of pingable members in the memberlist
218218func (m * memberlist ) NumPingableMembers () (n int ) {
219219 m .members .RLock ()
220+ defer m .members .RUnlock ()
220221 for _ , member := range m .members .list {
221222 if m .Pingable (* member ) {
222223 n ++
223224 }
224225 }
225- m .members .RUnlock ()
226226
227227 return n
228228}
@@ -232,6 +232,8 @@ func (m *memberlist) RandomPingableMembers(n int, excluding map[string]bool) []M
232232 members := make ([]Member , 0 , n )
233233
234234 m .members .RLock ()
235+ defer m .members .RUnlock ()
236+
235237 indices := rand .Perm (len (m .members .list ))
236238 for _ , index := range indices {
237239 member := m .members .list [index ]
@@ -242,22 +244,21 @@ func (m *memberlist) RandomPingableMembers(n int, excluding map[string]bool) []M
242244 }
243245 }
244246 }
245- m .members .RUnlock ()
246247 return members
247248}
248249
249250// returns an slice of (copied) members representing the current state of the
250251// membership. The membership will be filtered by the predicates provided.
251252func (m * memberlist ) GetMembers (predicates ... MemberPredicate ) (members []Member ) {
252253 m .members .RLock ()
254+ defer m .members .RUnlock ()
255+
253256 members = make ([]Member , 0 , len (m .members .list ))
254257 for _ , member := range m .members .list {
255258 if MemberMatchesPredicates (* member , predicates ... ) {
256259 members = append (members , * member )
257260 }
258261 }
259- m .members .RUnlock ()
260-
261262 return
262263}
263264
@@ -312,8 +313,8 @@ func (m *memberlist) SetLocalLabel(key, value string) error {
312313// argument indicates if the key was present on the node or not
313314func (m * memberlist ) GetLocalLabel (key string ) (string , bool ) {
314315 m .members .RLock ()
316+ defer m .members .RUnlock ()
315317 value , has := m .local .Labels [key ]
316- m .members .RUnlock ()
317318 return value , has
318319}
319320
@@ -531,7 +532,7 @@ func (m *memberlist) Update(changes []Change) (applied []Change) {
531532
532533 var memberChanges []membership.MemberChange
533534
534- m .Lock ()
535+ m .updateLock . Lock ()
535536
536537 // run through all changes received and figure out if they need to be accepted
537538 m .members .Lock ()
@@ -625,7 +626,7 @@ func (m *memberlist) Update(changes []Change) (applied []Change) {
625626 })
626627 }
627628
628- m .Unlock ()
629+ m .updateLock . Unlock ()
629630 return applied
630631}
631632
@@ -659,15 +660,15 @@ func (m *memberlist) getJoinPosition() int {
659660// shuffles the member list
660661func (m * memberlist ) Shuffle () {
661662 m .members .Lock ()
663+ defer m .members .Unlock ()
662664 m .members .list = shuffle (m .members .list )
663- m .members .Unlock ()
664665}
665666
666667// String returns a JSON string
667668func (m * memberlist ) String () string {
668669 m .members .RLock ()
670+ defer m .members .RUnlock ()
669671 str , _ := json .Marshal (m .members .list ) // will never return error (presumably)
670- m .members .RUnlock ()
671672 return string (str )
672673}
673674
@@ -682,12 +683,13 @@ func (m *memberlist) CountMembers(predicates ...MemberPredicate) int {
682683 count := 0
683684
684685 m .members .RLock ()
686+ defer m .members .RUnlock ()
687+
685688 for _ , member := range m .members .list {
686689 if MemberMatchesPredicates (* member , predicates ... ) {
687690 count ++
688691 }
689692 }
690- m .members .RUnlock ()
691693
692694 return count
693695}
0 commit comments