1
0
mirror of https://github.com/rancher/steve.git synced 2025-09-22 03:47:26 +00:00

Fix send to closed channel panic in watch (#817)

This commit is contained in:
Tom Lebreux
2025-09-10 15:09:25 -04:00
committed by GitHub
parent ca3fa10db5
commit 45a3b07816
2 changed files with 70 additions and 0 deletions

View File

@@ -399,6 +399,11 @@ func (l *ListOptionIndexer) Watch(ctx context.Context, opts WatchOptions, events
return nil return nil
}) })
if err != nil { if err != nil {
// We might have added a watcher but the transaction failed in
// which case we still want to remove the watcher
if key != nil {
l.removeWatcher(key)
}
return err return err
} }

View File

@@ -3505,3 +3505,68 @@ func TestNonNumberResourceVersion(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
assert.Equal(t, expectedList.Items, list.Items) assert.Equal(t, expectedList.Items, list.Items)
} }
// Test that we don't panic in case the transaction fails but stil manages to add a watcher
func TestWatchCancel(t *testing.T) {
startWatcher := func(ctx context.Context, loi *ListOptionIndexer, rv string) (chan watch.Event, chan error) {
eventsCh := make(chan watch.Event, 1)
errCh := make(chan error, 1)
go func() {
watchErr := loi.Watch(ctx, WatchOptions{ResourceVersion: rv}, eventsCh)
errCh <- watchErr
close(eventsCh)
}()
time.Sleep(100 * time.Millisecond)
return eventsCh, errCh
}
ctx := context.Background()
opts := ListOptionIndexerOptions{
Fields: [][]string{{"metadata", "somefield"}},
IsNamespaced: true,
}
loi, dbPath, err := makeListOptionIndexer(ctx, opts, false, emptyNamespaceList)
defer cleanTempFiles(dbPath)
assert.NoError(t, err)
foo := &unstructured.Unstructured{
Object: map[string]any{
"metadata": map[string]any{
"name": "foo",
},
},
}
foo.SetResourceVersion("100")
foo2 := foo.DeepCopy()
foo2.SetResourceVersion("200")
foo3 := foo.DeepCopy()
foo3.SetResourceVersion("300")
err = loi.Add(foo)
assert.NoError(t, err)
loi.Add(foo2)
assert.NoError(t, err)
loi.Add(foo3)
assert.NoError(t, err)
watchCtx, watchCancel := context.WithCancel(ctx)
eventsCh, errCh := startWatcher(watchCtx, loi, "100")
<-eventsCh
watchCancel()
<-eventsCh
go func() {
foo4 := foo.DeepCopy()
foo4.SetResourceVersion("400")
loi.Add(foo4)
}()
<-errCh
time.Sleep(1 * time.Second)
}