From 330dcb43d7415922d07b6836d411eb221fb03ed0 Mon Sep 17 00:00:00 2001 From: Karan Date: Mon, 15 Dec 2025 03:15:08 +0530 Subject: [PATCH] Fix goroutine leak in pluginmanager test Use a buffered channel for the operation start signal to prevent goroutines from blocking indefinitely. When the test receiver times out before all goroutines send their signal, an unbuffered channel causes those goroutines to block forever on the send operation. The buffer size is computed dynamically using max() to ensure it always accommodates the maximum number of concurrent operations any test may spawn. --- .../operationexecutor/operation_executor_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/kubelet/pluginmanager/operationexecutor/operation_executor_test.go b/pkg/kubelet/pluginmanager/operationexecutor/operation_executor_test.go index f9e62c66ddc..f903bd93024 100644 --- a/pkg/kubelet/pluginmanager/operationexecutor/operation_executor_test.go +++ b/pkg/kubelet/pluginmanager/operationexecutor/operation_executor_test.go @@ -34,6 +34,10 @@ import ( const ( numPluginsToRegister = 2 numPluginsToUnregister = 2 + // maxConcurrentOperations is the buffer size for the ch channel. + // Must be >= max number of goroutines any test spawns to prevent + // goroutine leaks when timeout fires before all sends complete. + maxConcurrentOperations = max(numPluginsToRegister, numPluginsToUnregister) ) var _ OperationGenerator = &fakeOperationGenerator{} @@ -178,7 +182,7 @@ loop: func setup(t *testing.T) (context.Context, chan interface{}, chan interface{}, OperationExecutor) { tCtx := ktesting.Init(t) - ch, quit := make(chan interface{}), make(chan interface{}) + ch, quit := make(chan interface{}, maxConcurrentOperations), make(chan interface{}) return tCtx, ch, quit, NewOperationExecutor(newFakeOperationGenerator(ch, quit)) }