Browse code

statsCollector: fix data race in run()

statsCollector.publishers must be protected to prevent
modifications during the iteration in run().
Being locked for a long time is bad, so pairs of containers &
publishers (pointers) are copied to release the lock fast.

Signed-off-by: Anton Tiurin <noxiouz@yandex.ru>

Anton Tiurin authored on 2015/04/24 06:39:05
Showing 1 changed files
... ...
@@ -76,22 +76,42 @@ func (s *statsCollector) unsubscribe(c *Container, ch chan interface{}) {
76 76
 }
77 77
 
78 78
 func (s *statsCollector) run() {
79
+	type publishersPair struct {
80
+		container *Container
81
+		publisher *pubsub.Publisher
82
+	}
83
+	// we cannot determine the capacity here.
84
+	// it will grow enough in first iteration
85
+	var pairs []publishersPair
86
+
79 87
 	for range time.Tick(s.interval) {
88
+		systemUsage, err := s.getSystemCpuUsage()
89
+		if err != nil {
90
+			logrus.Errorf("collecting system cpu usage: %v", err)
91
+			continue
92
+		}
93
+
94
+		// it does not make sense in the first iteration,
95
+		// but saves allocations in further iterations
96
+		pairs = pairs[:0]
97
+
98
+		s.m.Lock()
80 99
 		for container, publisher := range s.publishers {
81
-			systemUsage, err := s.getSystemCpuUsage()
82
-			if err != nil {
83
-				logrus.Errorf("collecting system cpu usage for %s: %v", container.ID, err)
84
-				continue
85
-			}
86
-			stats, err := container.Stats()
100
+			// copy pointers here to release the lock ASAP
101
+			pairs = append(pairs, publishersPair{container, publisher})
102
+		}
103
+		s.m.Unlock()
104
+
105
+		for _, pair := range pairs {
106
+			stats, err := pair.container.Stats()
87 107
 			if err != nil {
88 108
 				if err != execdriver.ErrNotRunning {
89
-					logrus.Errorf("collecting stats for %s: %v", container.ID, err)
109
+					logrus.Errorf("collecting stats for %s: %v", pair.container.ID, err)
90 110
 				}
91 111
 				continue
92 112
 			}
93 113
 			stats.SystemUsage = systemUsage
94
-			publisher.Publish(stats)
114
+			pair.publisher.Publish(stats)
95 115
 		}
96 116
 	}
97 117
 }