From 3cd685e93d1b597f8c0dda8f3c1ca5184bb5d9f5 Mon Sep 17 00:00:00 2001 From: Benedikt Reinartz Date: Tue, 1 Oct 2024 20:14:14 +0200 Subject: [PATCH] Use the BinaryFormatter only on .NET FW and Mono --- .../StateSerialization/MethodSerialization.cs | 4 ++ .../StateSerialization/NoopFormatter.cs | 14 ------- src/runtime/StateSerialization/RuntimeData.cs | 40 ++++++++++++------- 3 files changed, 30 insertions(+), 28 deletions(-) delete mode 100644 src/runtime/StateSerialization/NoopFormatter.cs diff --git a/src/embed_tests/StateSerialization/MethodSerialization.cs b/src/embed_tests/StateSerialization/MethodSerialization.cs index 80b7a08ee..b240d7ecf 100644 --- a/src/embed_tests/StateSerialization/MethodSerialization.cs +++ b/src/embed_tests/StateSerialization/MethodSerialization.cs @@ -33,6 +33,10 @@ static T SerializationRoundtrip(T item) { using var buf = new MemoryStream(); var formatter = RuntimeData.CreateFormatter(); + + if (formatter == null) + Assert.Inconclusive("Failed to create formatter for state serialization"); + formatter.Serialize(buf, item); buf.Position = 0; return (T)formatter.Deserialize(buf); diff --git a/src/runtime/StateSerialization/NoopFormatter.cs b/src/runtime/StateSerialization/NoopFormatter.cs deleted file mode 100644 index f05b7ebb2..000000000 --- a/src/runtime/StateSerialization/NoopFormatter.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.IO; -using System.Runtime.Serialization; - -namespace Python.Runtime; - -public class NoopFormatter : IFormatter { - public object Deserialize(Stream s) => throw new NotImplementedException(); - public void Serialize(Stream s, object o) {} - - public SerializationBinder? Binder { get; set; } - public StreamingContext Context { get; set; } - public ISurrogateSelector? SurrogateSelector { get; set; } -} diff --git a/src/runtime/StateSerialization/RuntimeData.cs b/src/runtime/StateSerialization/RuntimeData.cs index 8eda9ce0b..584e43f8b 100644 --- a/src/runtime/StateSerialization/RuntimeData.cs +++ b/src/runtime/StateSerialization/RuntimeData.cs @@ -16,21 +16,23 @@ namespace Python.Runtime public static class RuntimeData { - public readonly static Func DefaultFormatterFactory = () => + public readonly static Func DefaultFormatterFactory = () => { try { - return new BinaryFormatter(); - } - catch - { - return new NoopFormatter(); + var fw = RuntimeInformation.FrameworkDescription; + if (fw.StartsWith(".NET Framework") || fw.StartsWith("Mono")) + { + return new BinaryFormatter(); + } } + catch {} + return null; }; - private static Func _formatterFactory { get; set; } = DefaultFormatterFactory; + private static Func _formatterFactory { get; set; } = DefaultFormatterFactory; - public static Func FormatterFactory + public static Func FormatterFactory { get => _formatterFactory; set @@ -82,6 +84,14 @@ static void ClearCLRData () internal static void Stash() { + ClearCLRData(); + + IFormatter? formatter = CreateFormatter(); + + if (formatter == null) + // No formatter defined, exit early + return; + var runtimeStorage = new PythonNetState { Metatype = MetaType.SaveRuntimeData(), @@ -91,7 +101,6 @@ internal static void Stash() SharedObjects = SaveRuntimeDataObjects(), }; - IFormatter formatter = CreateFormatter(); var ms = new MemoryStream(); formatter.Serialize(ms, runtimeStorage); @@ -102,11 +111,10 @@ internal static void Stash() Marshal.WriteIntPtr(mem, (IntPtr)ms.Length); Marshal.Copy(data, 0, mem + IntPtr.Size, (int)ms.Length); - ClearCLRData(); - using NewReference capsule = PyCapsule_New(mem, IntPtr.Zero, IntPtr.Zero); int res = PySys_SetObject("clr_data", capsule.BorrowOrThrow()); PythonException.ThrowIfIsNotZero(res); + PostStashHook?.Invoke(); } @@ -124,6 +132,12 @@ internal static void RestoreRuntimeData() private static void RestoreRuntimeDataImpl() { + IFormatter? formatter = CreateFormatter(); + + if (formatter == null) + // No formatter defined, exit early + return; + PreRestoreHook?.Invoke(); BorrowedReference capsule = PySys_GetObject("clr_data"); if (capsule.IsNull) @@ -135,7 +149,6 @@ private static void RestoreRuntimeDataImpl() byte[] data = new byte[length]; Marshal.Copy(mem + IntPtr.Size, data, 0, length); var ms = new MemoryStream(data); - var formatter = CreateFormatter(); var storage = (PythonNetState)formatter.Deserialize(ms); PyCLRMetaType = MetaType.RestoreRuntimeData(storage.Metatype); @@ -373,9 +386,8 @@ public static MemoryStream GetSerializationData(string key) return new MemoryStream(buffer, writable:false); } - internal static IFormatter CreateFormatter() + internal static IFormatter? CreateFormatter() { - if (FormatterType != null) { return (IFormatter)Activator.CreateInstance(FormatterType);