mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
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>
This commit is contained in:
parent
b31d154294
commit
11a5f1af01
1 changed files with 28 additions and 8 deletions
|
@ -76,22 +76,42 @@ func (s *statsCollector) unsubscribe(c *Container, ch chan interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *statsCollector) run() {
|
func (s *statsCollector) run() {
|
||||||
|
type publishersPair struct {
|
||||||
|
container *Container
|
||||||
|
publisher *pubsub.Publisher
|
||||||
|
}
|
||||||
|
// we cannot determine the capacity here.
|
||||||
|
// it will grow enough in first iteration
|
||||||
|
var pairs []publishersPair
|
||||||
|
|
||||||
for range time.Tick(s.interval) {
|
for range time.Tick(s.interval) {
|
||||||
|
systemUsage, err := s.getSystemCpuUsage()
|
||||||
|
if err != nil {
|
||||||
|
logrus.Errorf("collecting system cpu usage: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// it does not make sense in the first iteration,
|
||||||
|
// but saves allocations in further iterations
|
||||||
|
pairs = pairs[:0]
|
||||||
|
|
||||||
|
s.m.Lock()
|
||||||
for container, publisher := range s.publishers {
|
for container, publisher := range s.publishers {
|
||||||
systemUsage, err := s.getSystemCpuUsage()
|
// copy pointers here to release the lock ASAP
|
||||||
if err != nil {
|
pairs = append(pairs, publishersPair{container, publisher})
|
||||||
logrus.Errorf("collecting system cpu usage for %s: %v", container.ID, err)
|
}
|
||||||
continue
|
s.m.Unlock()
|
||||||
}
|
|
||||||
stats, err := container.Stats()
|
for _, pair := range pairs {
|
||||||
|
stats, err := pair.container.Stats()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != execdriver.ErrNotRunning {
|
if err != execdriver.ErrNotRunning {
|
||||||
logrus.Errorf("collecting stats for %s: %v", container.ID, err)
|
logrus.Errorf("collecting stats for %s: %v", pair.container.ID, err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
stats.SystemUsage = systemUsage
|
stats.SystemUsage = systemUsage
|
||||||
publisher.Publish(stats)
|
pair.publisher.Publish(stats)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue