From 140d7de7be26a12dd2710f74dcf80e5b1027dafc Mon Sep 17 00:00:00 2001 From: Avinesh Singh Date: Fri, 2 Feb 2024 03:23:23 +0530 Subject: [PATCH] Fix: Exec provider potential deadlock (#1457) * Fix: Exec Process deadlock WaitForExit should have been called after all other methods are called on the process * Non-blocking standard output stream parsing * Force buffer flush for non-infinite timeout --- ...ubernetesClientConfiguration.ConfigFile.cs | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs index e74660b..ed51122 100644 --- a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs +++ b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Net; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; +using System.Text; namespace k8s { @@ -537,12 +538,29 @@ namespace k8s try { - if (!process.WaitForExit((int)(ExecTimeout.TotalMilliseconds))) + var output = new StringBuilder(); + process.OutputDataReceived += (_, args) => + { + if (args.Data != null) + { + output.Append(args.Data); + } + }; + process.BeginOutputReadLine(); + + if (!process.WaitForExit((int)ExecTimeout.TotalMilliseconds)) { throw new KubeConfigException("external exec failed due to timeout"); } - var responseObject = KubernetesJson.Deserialize(process.StandardOutput.ReadToEnd()); + // Force flush the output buffer to avoid case of missing data + if (ExecTimeout != Timeout.InfiniteTimeSpan) + { + process.WaitForExit(); + } + + var responseObject = KubernetesJson.Deserialize(output.ToString()); + if (responseObject == null || responseObject.ApiVersion != config.ApiVersion) { throw new KubeConfigException( @@ -553,10 +571,8 @@ namespace k8s { return responseObject; } - else - { - throw new KubeConfigException($"external exec failed missing token or clientCertificateData field in plugin output"); - } + + throw new KubeConfigException($"external exec failed missing token or clientCertificateData field in plugin output"); } catch (JsonException ex) {