Skip to content

Commit 2112ab6

Browse files
hypnoglowaeneasr
authored andcommitted
rule: Fix panic on send on closed channel (#225)
Closes #224
1 parent 8f4a518 commit 2112ab6

File tree

1 file changed

+22
-17
lines changed

1 file changed

+22
-17
lines changed

rule/fetcher_default.go

+22-17
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ type FetcherDefault struct {
6161
watching []url.URL
6262

6363
lock sync.Mutex
64+
wg sync.WaitGroup
6465
}
6566

6667
func NewFetcherDefault(
@@ -119,9 +120,7 @@ func (f *FetcherDefault) configUpdate(ctx context.Context, watcher *fsnotify.Wat
119120
}
120121
}
121122
for _, source := range replace {
122-
go func(s url.URL) {
123-
events <- event{et: eventFileChanged, path: s, source: "config_update"}
124-
}(source)
123+
f.enqueueEvent(events, event{et: eventFileChanged, path: source, source: "config_update"})
125124
}
126125
return nil
127126
}
@@ -162,8 +161,13 @@ func (f *FetcherDefault) Watch(ctx context.Context) error {
162161
defer watcher.Close()
163162

164163
events := make(chan event)
165-
defer close(events)
166-
return f.watch(ctx, watcher, events)
164+
err = f.watch(ctx, watcher, events)
165+
166+
// Close the channel only when all child goroutines exit
167+
f.wg.Wait()
168+
close(events)
169+
170+
return err
167171
}
168172

169173
func (f *FetcherDefault) watch(ctx context.Context, watcher *fsnotify.Watcher, events chan event) error {
@@ -176,16 +180,12 @@ func (f *FetcherDefault) watch(ctx context.Context, watcher *fsnotify.Watcher, e
176180
return nil
177181
}
178182

179-
go func() {
180-
events <- event{et: eventRepositoryConfigChange, source: "viper_watcher"}
181-
}()
183+
f.enqueueEvent(events, event{et: eventRepositoryConfigChange, source: "viper_watcher"})
182184

183185
return nil
184186
})
185187

186-
go func() {
187-
events <- event{et: eventRepositoryConfigChange, source: "entrypoint"}
188-
}()
188+
f.enqueueEvent(events, event{et: eventRepositoryConfigChange, source: "entrypoint"})
189189

190190
for {
191191
select {
@@ -199,9 +199,7 @@ func (f *FetcherDefault) watch(ctx context.Context, watcher *fsnotify.Watcher, e
199199
f.r.Logger().
200200
Debugf("Detected that a access rule repository file has been removed, reloading config.")
201201
// If a file was removed it's likely that the config changed as well - reload!
202-
go func() {
203-
events <- event{et: eventRepositoryConfigChange, source: "fsnotify_remove"}
204-
}()
202+
f.enqueueEvent(events, event{et: eventRepositoryConfigChange, source: "fsnotify_remove"})
205203
continue
206204
}
207205

@@ -216,9 +214,7 @@ func (f *FetcherDefault) watch(ctx context.Context, watcher *fsnotify.Watcher, e
216214
WithField("op", e.Op.String()).
217215
Debugf("Detected access rule repository file change.")
218216

219-
go func() {
220-
events <- event{et: eventFileChanged, path: *source, source: "fsnotify_update"}
221-
}()
217+
f.enqueueEvent(events, event{et: eventFileChanged, path: *source, source: "fsnotify_update"})
222218
case e, ok := <-events:
223219
if !ok {
224220
// channel was closed
@@ -255,6 +251,15 @@ func (f *FetcherDefault) watch(ctx context.Context, watcher *fsnotify.Watcher, e
255251
}
256252
}
257253

254+
func (f *FetcherDefault) enqueueEvent(events chan event, evt event) {
255+
f.wg.Add(1)
256+
go func() {
257+
defer f.wg.Done()
258+
259+
events <- evt
260+
}()
261+
}
262+
258263
func (f *FetcherDefault) fetch(source url.URL) ([]Rule, error) {
259264
switch source.Scheme {
260265
case "http":

0 commit comments

Comments
 (0)