From 09f8f20e99c667033f964e04a1b1ce6d9493c392 Mon Sep 17 00:00:00 2001 From: Alex Mitchell Date: Wed, 3 Apr 2024 15:15:31 +1030 Subject: [PATCH] Prevent concurrent use of YAML serializer / deserializer 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 b40ed8d4..803c2bb6 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(); }