From 25b53a8233139941d6e48c1fa84a69d9832148a8 Mon Sep 17 00:00:00 2001 From: Karthik Rajan Date: Thu, 23 Jul 2026 15:57:39 +0530 Subject: [PATCH 1/2] added request timeout Signed-off-by: Karthik Rajan --- pkg/karmadactl/util/completion/completion.go | 73 +++++++++++++------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/pkg/karmadactl/util/completion/completion.go b/pkg/karmadactl/util/completion/completion.go index d97d51f7d06d..787e34588225 100644 --- a/pkg/karmadactl/util/completion/completion.go +++ b/pkg/karmadactl/util/completion/completion.go @@ -42,6 +42,8 @@ import ( "github.com/karmada-io/karmada/pkg/karmadactl/util" ) +const completionRequestTimeout = 5 * time.Second + var factory util.Factory // SetFactoryForCompletion Store the factory which is needed by the completion functions. @@ -256,35 +258,58 @@ func compGetResourceList(restClientGetter genericclioptions.RESTClientGetter, cm o.PrintFlags.OutputFormat = ptr.To("name") o.Cached = true o.Verbs = []string{"get"} - // TODO: Should set --request-timeout=5s - if err := o.Complete(restClientGetter, cmd, nil); err != nil { - return nil - } + // Use a context with timeout to prevent indefinite waiting during shell completion + ctx, cancel := context.WithTimeout(context.Background(), completionRequestTimeout) + defer cancel() - // Ignore errors as the output may still be valid - if err := o.RunAPIResources(); err != nil { - return nil - } + // Run the completion operations with timeout protection + resultChan := make(chan []string, 1) + errorChan := make(chan error, 1) - // Resources can be a comma-separated list. The last element is then - // the one we should complete. For example if toComplete=="pods,secre" - // we should return "pods,secrets" - prefix := "" - suffix := toComplete - lastIdx := strings.LastIndex(toComplete, ",") - if lastIdx != -1 { - prefix = toComplete[0 : lastIdx+1] - suffix = toComplete[lastIdx+1:] - } - var comps []string - resources := strings.SplitSeq(buf.String(), "\n") - for res := range resources { - if res != "" && strings.HasPrefix(res, suffix) { - comps = append(comps, fmt.Sprintf("%s%s", prefix, res)) + go func() { + if err := o.Complete(restClientGetter, cmd, nil); err != nil { + errorChan <- err + return + } + + // Ignore errors as the output may still be valid + if err := o.RunAPIResources(); err != nil { + errorChan <- err + return + } + + // Resources can be a comma-separated list. The last element is then + // the one we should complete. For example if toComplete=="pods,secre" + // we should return "pods,secrets" + prefix := "" + suffix := toComplete + lastIdx := strings.LastIndex(toComplete, ",") + if lastIdx != -1 { + prefix = toComplete[0 : lastIdx+1] + suffix = toComplete[lastIdx+1:] } + var comps []string + resources := strings.SplitSeq(buf.String(), "\n") + for res := range resources { + if res != "" && strings.HasPrefix(res, suffix) { + comps = append(comps, fmt.Sprintf("%s%s", prefix, res)) + } + } + resultChan <- comps + }() + + // Wait for either completion or timeout + select { + case comps := <-resultChan: + return comps + case <-errorChan: + // Error occurred, return nil to fail gracefully during completion + return nil + case <-ctx.Done(): + // Timeout occurred, return empty completion list to prevent shell hang + return nil } - return comps } // resourceTypeAndNameCompletionFunc Returns a completion function that completes resource types From e8b6c241e47008db02a38f79a22949441498174f Mon Sep 17 00:00:00 2001 From: Karthik Rajan Date: Thu, 23 Jul 2026 16:19:58 +0530 Subject: [PATCH 2/2] updated suggetions Signed-off-by: Karthik Rajan --- pkg/karmadactl/util/completion/completion.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkg/karmadactl/util/completion/completion.go b/pkg/karmadactl/util/completion/completion.go index 0b3d477c72c7..fde603b5f2e7 100644 --- a/pkg/karmadactl/util/completion/completion.go +++ b/pkg/karmadactl/util/completion/completion.go @@ -288,10 +288,7 @@ func compGetResourceList(restClientGetter genericclioptions.RESTClientGetter, cm } // Ignore errors as the output may still be valid - if err := o.RunAPIResources(); err != nil { - errorChan <- err - return - } + _ = o.RunAPIResources() // Resources can be a comma-separated list. The last element is then // the one we should complete. For example if toComplete=="pods,secre"