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(