From 7dad2f31a86f68ee95bc24426048ed7f7a33b5ce Mon Sep 17 00:00:00 2001 From: Alex Mitchell Date: Sat, 6 Apr 2024 16:37:27 +1030 Subject: [PATCH] Prevent concurrent use of YAML serializer / deserializer (#1544) YamlDotNet ISerializer and IDeserializer are not thread-safe --- src/KubernetesClient/KubernetesYaml.cs | 38 ++++++++++++++++++++------ 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/KubernetesClient/KubernetesYaml.cs b/src/KubernetesClient/KubernetesYaml.cs index b40ed8d44..803c2bb64 100644 --- a/src/KubernetesClient/KubernetesYaml.cs +++ b/src/KubernetesClient/KubernetesYaml.cs @@ -12,6 +12,9 @@ namespace k8s /// public static class KubernetesYaml { + private static readonly object DeserializerLockObject = new object(); + private static readonly object SerializerLockObject = new object(); + private static DeserializerBuilder CommonDeserializerBuilder => new DeserializerBuilder() .WithNamingConvention(CamelCaseNamingConvention.Instance) @@ -156,8 +159,11 @@ public static List LoadAllFromString(string content, IDictionary(); while (parser.Accept(out _)) { - var dict = GetDeserializer(strict).Deserialize>(parser); - types.Add(mergedTypeMap[dict["apiVersion"] + "/" + dict["kind"]]); + lock (DeserializerLockObject) + { + var dict = GetDeserializer(strict).Deserialize>(parser); + types.Add(mergedTypeMap[dict["apiVersion"] + "/" + dict["kind"]]); + } } parser = new MergingParser(new Parser(new StringReader(content))); @@ -167,8 +173,11 @@ public static List LoadAllFromString(string content, IDictionary(out _)) { var objType = types[ix++]; - var obj = GetDeserializer(strict).Deserialize(parser, objType); - results.Add(obj); + lock (DeserializerLockObject) + { + var obj = GetDeserializer(strict).Deserialize(parser, objType); + results.Add(obj); + } } return results; @@ -204,13 +213,19 @@ public static string SaveToString(T value) public static TValue Deserialize(string yaml, bool strict = false) { using var reader = new StringReader(yaml); - return GetDeserializer(strict).Deserialize(new MergingParser(new Parser(reader))); + lock (DeserializerLockObject) + { + return GetDeserializer(strict).Deserialize(new MergingParser(new Parser(reader))); + } } public static TValue Deserialize(Stream yaml, bool strict = false) { using var reader = new StreamReader(yaml); - return GetDeserializer(strict).Deserialize(new MergingParser(new Parser(reader))); + lock (DeserializerLockObject) + { + return GetDeserializer(strict).Deserialize(new MergingParser(new Parser(reader))); + } } public static string SerializeAll(IEnumerable values) @@ -231,7 +246,11 @@ public static string SerializeAll(IEnumerable values) if (value != null) { emitter.Emit(new DocumentStart()); - Serializer.SerializeValue(emitter, value, value.GetType()); + lock (SerializerLockObject) + { + Serializer.SerializeValue(emitter, value, value.GetType()); + } + emitter.Emit(new DocumentEnd(true)); } } @@ -252,7 +271,10 @@ public static string Serialize(object value) emitter.Emit(new StreamStart()); emitter.Emit(new DocumentStart()); - Serializer.SerializeValue(emitter, value, value.GetType()); + lock (SerializerLockObject) + { + Serializer.SerializeValue(emitter, value, value.GetType()); + } return stringBuilder.ToString(); }