Преглед на файлове

pkg/types: Avoid potential double lock of tsafeSet.

(tsafeSet).Sub and (tsafeSet).Equals can cause double lock bug if ts and other is pointing the same variable

gofmt the code and add some comments
lzhfromustc преди 6 години
родител
ревизия
0e7173b447
променени са 1 файла, в които са добавени 17 реда и са изтрити 0 реда
  1. 17 0
      pkg/types/set.go

+ 17 - 0
pkg/types/set.go

@@ -148,6 +148,14 @@ func (ts *tsafeSet) Contains(value string) (exists bool) {
 func (ts *tsafeSet) Equals(other Set) bool {
 func (ts *tsafeSet) Equals(other Set) bool {
 	ts.m.RLock()
 	ts.m.RLock()
 	defer ts.m.RUnlock()
 	defer ts.m.RUnlock()
+
+	// If ts and other represent the same variable, avoid calling
+	// ts.us.Equals(other), to avoid double RLock bug
+	if _other, ok := other.(*tsafeSet); ok {
+		if _other == ts {
+			return true
+		}
+	}
 	return ts.us.Equals(other)
 	return ts.us.Equals(other)
 }
 }
 
 
@@ -173,6 +181,15 @@ func (ts *tsafeSet) Copy() Set {
 func (ts *tsafeSet) Sub(other Set) Set {
 func (ts *tsafeSet) Sub(other Set) Set {
 	ts.m.RLock()
 	ts.m.RLock()
 	defer ts.m.RUnlock()
 	defer ts.m.RUnlock()
+
+	// If ts and other represent the same variable, avoid calling
+	// ts.us.Sub(other), to avoid double RLock bug
+	if _other, ok := other.(*tsafeSet); ok {
+		if _other == ts {
+			usResult := NewUnsafeSet()
+			return &tsafeSet{usResult, sync.RWMutex{}}
+		}
+	}
 	usResult := ts.us.Sub(other).(*unsafeSet)
 	usResult := ts.us.Sub(other).(*unsafeSet)
 	return &tsafeSet{usResult, sync.RWMutex{}}
 	return &tsafeSet{usResult, sync.RWMutex{}}
 }
 }