@@ -102,8 +102,12 @@ func (f *FetcherDefault) watchLocalFiles(ctx context.Context) {
102102 if cancel , ok := f .cancelWatchers [fp ]; ! ok {
103103 // watch all files we are not yet watching
104104 repoChanged = true
105- ctx , cancelWatchers [fp ] = context .WithCancel (ctx )
106- w , err := watcherx .WatchFile (ctx , fp , f .events )
105+ // Derive each file's context from the caller's ctx, not from the
106+ // previous iteration's, so cancelling one file's watcher does not
107+ // cancel the others.
108+ var fileCtx context.Context
109+ fileCtx , cancelWatchers [fp ] = context .WithCancel (ctx )
110+ w , err := watcherx .WatchFile (fileCtx , fp , f .events )
107111 if err != nil {
108112 f .registry .Logger ().WithError (err ).WithField ("file" , fp ).Error ("Unable to watch file, ignoring it." )
109113 continue
@@ -144,6 +148,12 @@ func (f *FetcherDefault) watchLocalFiles(ctx context.Context) {
144148}
145149
146150func (f * FetcherDefault ) Watch (ctx context.Context ) error {
151+ // Start the local update consumer before watching files. watchLocalFiles
152+ // forces an initial read via DispatchNow, which sends on the unbuffered
153+ // f.events channel; without a reader already running, that send can block
154+ // and deadlock the watcher setup.
155+ go f .processLocalUpdates (ctx )
156+
147157 f .watchLocalFiles (ctx )
148158
149159 getRemoteRepos := func () map [url.URL ]struct {} {
@@ -191,7 +201,6 @@ func (f *FetcherDefault) Watch(ctx context.Context) error {
191201 remoteRepos = newRemoteRepos
192202 })
193203
194- go f .processLocalUpdates (ctx )
195204 return nil
196205}
197206
0 commit comments