Browse code

Fix a race in pkg/discovery/memory

Fix #22964

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>

Akihiro Suda authored on 2016/05/25 11:52:35
Showing 1 changed files
... ...
@@ -1,16 +1,18 @@
1 1
 package memory
2 2
 
3 3
 import (
4
+	"sync"
4 5
 	"time"
5 6
 
6 7
 	"github.com/docker/docker/pkg/discovery"
7 8
 )
8 9
 
9
-// Discovery implements a descovery backend that keeps
10
+// Discovery implements a discovery backend that keeps
10 11
 // data in memory.
11 12
 type Discovery struct {
12 13
 	heartbeat time.Duration
13 14
 	values    []string
15
+	mu        sync.Mutex
14 16
 }
15 17
 
16 18
 func init() {
... ...
@@ -41,21 +43,27 @@ func (s *Discovery) Watch(stopCh <-chan struct{}) (<-chan discovery.Entries, <-c
41 41
 
42 42
 		// Send the initial entries if available.
43 43
 		var currentEntries discovery.Entries
44
+		var err error
45
+
46
+		s.mu.Lock()
44 47
 		if len(s.values) > 0 {
45
-			var err error
46 48
 			currentEntries, err = discovery.CreateEntries(s.values)
47
-			if err != nil {
48
-				errCh <- err
49
-			} else {
50
-				ch <- currentEntries
51
-			}
49
+		}
50
+		s.mu.Unlock()
51
+
52
+		if err != nil {
53
+			errCh <- err
54
+		} else if currentEntries != nil {
55
+			ch <- currentEntries
52 56
 		}
53 57
 
54 58
 		// Periodically send updates.
55 59
 		for {
56 60
 			select {
57 61
 			case <-ticker.C:
62
+				s.mu.Lock()
58 63
 				newEntries, err := discovery.CreateEntries(s.values)
64
+				s.mu.Unlock()
59 65
 				if err != nil {
60 66
 					errCh <- err
61 67
 					continue
... ...
@@ -78,6 +86,8 @@ func (s *Discovery) Watch(stopCh <-chan struct{}) (<-chan discovery.Entries, <-c
78 78
 
79 79
 // Register adds a new address to the discovery.
80 80
 func (s *Discovery) Register(addr string) error {
81
+	s.mu.Lock()
81 82
 	s.values = append(s.values, addr)
83
+	s.mu.Unlock()
82 84
 	return nil
83 85
 }