From 7508ffeec1d7f38073b0928ae44f3bc9abb1de2a Mon Sep 17 00:00:00 2001 From: Ivan Josipovic <9521987+IvanJosipovic@users.noreply.github.com> Date: Sun, 30 Apr 2023 22:28:17 -0700 Subject: [PATCH] fix: Exec hangs (#1267) * fix: exec hanging * fix: exec hang * chore: increase buffer * chore: add StandardOutput timeout * chore: switch to event based * chore: simplify logic * chore: fix logic * fix: remove async * chore: simplify logic * fix: revert to non Event based logic * fix: simplify logic * fix: switch to GetAwaiter().GetResult() * feat: externalize exec timeout * feat: send errors to event * chore: formatting * fix: add null check for event handler * feat: switch to TimeSpan --- ...ubernetesClientConfiguration.ConfigFile.cs | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs index 9d439ad..8508583 100644 --- a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs +++ b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs @@ -28,6 +28,16 @@ namespace k8s // For testing internal static string KubeConfigEnvironmentVariable { get; set; } = "KUBECONFIG"; + /// + /// Exec process timeout + /// + public static TimeSpan ExecTimeout { get; set; } = TimeSpan.FromMinutes(2); + + /// + /// Exec process Standard Errors + /// + public static event EventHandler ExecStdError; + /// /// Initializes a new instance of the from default locations /// If the KUBECONFIG environment variable is set, then that will be used. @@ -552,25 +562,25 @@ namespace k8s try { process.Start(); + if (ExecStdError != null) + { + process.ErrorDataReceived += (s, e) => ExecStdError.Invoke(s, e); + process.BeginErrorReadLine(); + } } catch (Exception ex) { throw new KubeConfigException($"external exec failed due to: {ex.Message}"); } - var stdout = process.StandardOutput.ReadToEnd(); - var stderr = process.StandardError.ReadToEnd(); - if (string.IsNullOrWhiteSpace(stderr) == false) - { - throw new KubeConfigException($"external exec failed due to: {stderr}"); - } - - // Wait for a maximum of 5 seconds, if a response takes longer probably something went wrong... - process.WaitForExit(5); - try { - var responseObject = KubernetesJson.Deserialize(stdout); + if (!process.WaitForExit((int)(ExecTimeout.TotalMilliseconds))) + { + throw new KubeConfigException("external exec failed due to timeout"); + } + + var responseObject = KubernetesJson.Deserialize(process.StandardOutput.ReadToEnd()); if (responseObject == null || responseObject.ApiVersion != config.ApiVersion) { throw new KubeConfigException(