mirror of https://github.com/docker/compose.git
watch: a new strategy for handling spurious events, hoping to fix race conditions (#163)
This commit is contained in:
parent
4801d2b1a4
commit
4562b0bf95
|
@ -134,6 +134,9 @@ func TestWatchNonExistentPath(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
f.fsync()
|
||||||
|
|
||||||
d1 := []byte("hello\ngo\n")
|
d1 := []byte("hello\ngo\n")
|
||||||
err = ioutil.WriteFile(path, d1, 0644)
|
err = ioutil.WriteFile(path, d1, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -20,21 +20,13 @@ type darwinNotify struct {
|
||||||
// so that, for recursive watches, we can guarantee that the path list doesn't
|
// so that, for recursive watches, we can guarantee that the path list doesn't
|
||||||
// change.
|
// change.
|
||||||
sm *sync.Mutex
|
sm *sync.Mutex
|
||||||
}
|
|
||||||
|
|
||||||
func (d *darwinNotify) isTrackingPath(path string) bool {
|
// ignore the first event that says the watched directory
|
||||||
d.sm.Lock()
|
// has been created. these are fired spuriously on initiation.
|
||||||
defer d.sm.Unlock()
|
ignoreCreatedEvents map[string]bool
|
||||||
for _, p := range d.stream.Paths {
|
|
||||||
if p == path {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *darwinNotify) loop() {
|
func (d *darwinNotify) loop() {
|
||||||
ignoredSpuriousEvents := make(map[string]bool, 0)
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-d.stop:
|
case <-d.stop:
|
||||||
|
@ -47,11 +39,20 @@ func (d *darwinNotify) loop() {
|
||||||
for _, e := range events {
|
for _, e := range events {
|
||||||
e.Path = filepath.Join("/", e.Path)
|
e.Path = filepath.Join("/", e.Path)
|
||||||
|
|
||||||
// ignore the first event that says the watched directory
|
|
||||||
// has been created. these are fired spuriously on initiation.
|
|
||||||
if e.Flags&fsevents.ItemCreated == fsevents.ItemCreated {
|
if e.Flags&fsevents.ItemCreated == fsevents.ItemCreated {
|
||||||
if !ignoredSpuriousEvents[e.Path] && d.isTrackingPath(e.Path) {
|
d.sm.Lock()
|
||||||
ignoredSpuriousEvents[e.Path] = true
|
shouldIgnore := d.ignoreCreatedEvents[e.Path]
|
||||||
|
if shouldIgnore {
|
||||||
|
d.ignoreCreatedEvents[e.Path] = false
|
||||||
|
} else {
|
||||||
|
// If we got a created event for something
|
||||||
|
// that's not on the ignore list, we assume
|
||||||
|
// we're done with the spurious events.
|
||||||
|
d.ignoreCreatedEvents = nil
|
||||||
|
}
|
||||||
|
d.sm.Unlock()
|
||||||
|
|
||||||
|
if shouldIgnore {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,6 +81,12 @@ func (d *darwinNotify) Add(name string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
es.Paths = append(es.Paths, name)
|
es.Paths = append(es.Paths, name)
|
||||||
|
|
||||||
|
if d.ignoreCreatedEvents == nil {
|
||||||
|
d.ignoreCreatedEvents = make(map[string]bool, 1)
|
||||||
|
}
|
||||||
|
d.ignoreCreatedEvents[name] = true
|
||||||
|
|
||||||
if len(es.Paths) == 1 {
|
if len(es.Paths) == 1 {
|
||||||
go d.loop()
|
go d.loop()
|
||||||
es.Start()
|
es.Start()
|
||||||
|
|
Loading…
Reference in New Issue