Browse code

Fix data race in TestLogEvent

Found with -race. Improve locking on Server.

Paul Nasrat authored on 2013/11/26 03:58:17
Showing 3 changed files
... ...
@@ -254,7 +254,7 @@ func getEvents(srv *Server, version float64, w http.ResponseWriter, r *http.Requ
254 254
 	wf.Flush()
255 255
 	if since != 0 {
256 256
 		// If since, send previous events that happened after the timestamp
257
-		for _, event := range srv.events {
257
+		for _, event := range srv.GetEvents() {
258 258
 			if event.Time >= since {
259 259
 				err := sendEvent(wf, &event)
260 260
 				if err != nil && err.Error() == "JSON error" {
... ...
@@ -959,6 +959,8 @@ func (srv *Server) poolAdd(kind, key string) error {
959 959
 }
960 960
 
961 961
 func (srv *Server) poolRemove(kind, key string) error {
962
+	srv.Lock()
963
+	defer srv.Unlock()
962 964
 	switch kind {
963 965
 	case "pull":
964 966
 		delete(srv.pullingPool, key)
... ...
@@ -1829,6 +1831,8 @@ func NewServer(eng *engine.Engine, config *DaemonConfig) (*Server, error) {
1829 1829
 }
1830 1830
 
1831 1831
 func (srv *Server) HTTPRequestFactory(metaHeaders map[string][]string) *utils.HTTPRequestFactory {
1832
+	srv.Lock()
1833
+	defer srv.Unlock()
1832 1834
 	if srv.reqFactory == nil {
1833 1835
 		ud := utils.NewHTTPUserAgentDecorator(srv.versionInfos()...)
1834 1836
 		md := &utils.HTTPMetaHeadersDecorator{
... ...
@@ -1843,7 +1847,7 @@ func (srv *Server) HTTPRequestFactory(metaHeaders map[string][]string) *utils.HT
1843 1843
 func (srv *Server) LogEvent(action, id, from string) *utils.JSONMessage {
1844 1844
 	now := time.Now().Unix()
1845 1845
 	jm := utils.JSONMessage{Status: action, ID: id, From: from, Time: now}
1846
-	srv.events = append(srv.events, jm)
1846
+	srv.AddEvent(jm)
1847 1847
 	for _, c := range srv.listeners {
1848 1848
 		select { // non blocking channel
1849 1849
 		case c <- jm:
... ...
@@ -1853,8 +1857,20 @@ func (srv *Server) LogEvent(action, id, from string) *utils.JSONMessage {
1853 1853
 	return &jm
1854 1854
 }
1855 1855
 
1856
+func (srv *Server) AddEvent(jm utils.JSONMessage) {
1857
+	srv.Lock()
1858
+	defer srv.Unlock()
1859
+	srv.events = append(srv.events, jm)
1860
+}
1861
+
1862
+func (srv *Server) GetEvents() []utils.JSONMessage {
1863
+	srv.RLock()
1864
+	defer srv.RUnlock()
1865
+	return srv.events
1866
+}
1867
+
1856 1868
 type Server struct {
1857
-	sync.Mutex
1869
+	sync.RWMutex
1858 1870
 	runtime     *Runtime
1859 1871
 	pullingPool map[string]struct{}
1860 1872
 	pushingPool map[string]struct{}
... ...
@@ -70,8 +70,9 @@ func TestLogEvent(t *testing.T) {
70 70
 
71 71
 	srv.LogEvent("fakeaction2", "fakeid", "fakeimage")
72 72
 
73
-	if len(srv.events) != 2 {
74
-		t.Fatalf("Expected 2 events, found %d", len(srv.events))
73
+	numEvents := len(srv.GetEvents())
74
+	if numEvents != 2 {
75
+		t.Fatalf("Expected 2 events, found %d", numEvents)
75 76
 	}
76 77
 	go func() {
77 78
 		time.Sleep(200 * time.Millisecond)
... ...
@@ -83,7 +84,7 @@ func TestLogEvent(t *testing.T) {
83 83
 	setTimeout(t, "Listening for events timed out", 2*time.Second, func() {
84 84
 		for i := 2; i < 4; i++ {
85 85
 			event := <-listener
86
-			if event != srv.events[i] {
86
+			if event != srv.GetEvents()[i] {
87 87
 				t.Fatalf("Event received it different than expected")
88 88
 			}
89 89
 		}