Skip to content

Commit e9cbb87

Browse files
committed
do not attempt to manually delete derived class instances after TypeManager is terminated and Python is shutting down
1 parent 5e041af commit e9cbb87

File tree

4 files changed

+18
-13
lines changed

4 files changed

+18
-13
lines changed

pythonnet.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repo", "Repo", "{441A0123-F
2525
EndProject
2626
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CI", "CI", "{D301657F-5EAF-4534-B280-B858D651B2E5}"
2727
ProjectSection(SolutionItems) = preProject
28+
.github\workflows\ARM.yml = .github\workflows\ARM.yml
2829
.github\workflows\main.yml = .github\workflows\main.yml
2930
.github\workflows\nuget-preview.yml = .github\workflows\nuget-preview.yml
3031
EndProjectSection

src/runtime/Runtime.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ private static string GetDefaultDllName(Version version)
5454
}
5555

5656
private static bool _isInitialized = false;
57-
5857
internal static bool IsInitialized => _isInitialized;
58+
private static bool _typesInitialized = false;
59+
internal static bool TypeManagerInitialized => _typesInitialized;
5960
internal static readonly bool Is32Bit = IntPtr.Size == 4;
6061

6162
// .NET core: System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
@@ -151,6 +152,7 @@ internal static void Initialize(bool initSigs = false)
151152
ClassManager.Reset();
152153
ClassDerivedObject.Reset();
153154
TypeManager.Initialize();
155+
_typesInitialized = true;
154156

155157
// Initialize modules that depend on the runtime class.
156158
AssemblyManager.Initialize();
@@ -272,6 +274,7 @@ internal static void Shutdown()
272274
NullGCHandles(ExtensionType.loadedExtensions);
273275
ClassManager.RemoveClasses();
274276
TypeManager.RemoveTypes();
277+
_typesInitialized = false;
275278

276279
MetaType.Release();
277280
PyCLRMetaType.Dispose();
@@ -291,9 +294,10 @@ internal static void Shutdown()
291294
Finalizer.Shutdown();
292295
InternString.Shutdown();
293296

297+
ResetPyMembers();
298+
294299
if (!HostedInPython)
295300
{
296-
ResetPyMembers();
297301
GC.Collect();
298302
GC.WaitForPendingFinalizers();
299303
PyGILState_Release(state);
@@ -310,7 +314,6 @@ internal static void Shutdown()
310314
}
311315
else
312316
{
313-
ResetPyMembers();
314317
PyGILState_Release(state);
315318
}
316319
}

src/runtime/TypeManager.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,7 @@ public void ResetSlots()
832832
var metatype = Runtime.PyObject_TYPE(Type);
833833
ManagedType.TryFreeGCHandle(Type, metatype);
834834
}
835+
Runtime.PyType_Modified(Type);
835836
}
836837

837838
public static IntPtr GetDefaultSlot(int offset)

src/runtime/Types/ClassDerived.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,7 @@ protected override NewReference NewObjectToPython(object obj, BorrowedReference
5959
// Decrement the python object's reference count.
6060
// This doesn't actually destroy the object, it just sets the reference to this object
6161
// to be a weak reference and it will be destroyed when the C# object is destroyed.
62-
if (!self.IsNull())
63-
{
64-
Runtime.XDecref(self.Steal());
65-
}
62+
Runtime.XDecref(self.Steal());
6663

6764
return Converter.ToPython(obj, type.Value);
6865
}
@@ -942,13 +939,16 @@ internal static void Finalize(IntPtr derived)
942939

943940
var type = Runtime.PyObject_TYPE(@ref.Borrow());
944941

945-
// rare case when it's needed
946-
// matches correspdonging PyObject_GC_UnTrack
947-
// in ClassDerivedObject.tp_dealloc
948-
Runtime.PyObject_GC_Del(@ref.Steal());
942+
if (!Runtime.HostedInPython || Runtime.TypeManagerInitialized)
943+
{
944+
// rare case when it's needed
945+
// matches correspdonging PyObject_GC_UnTrack
946+
// in ClassDerivedObject.tp_dealloc
947+
Runtime.PyObject_GC_Del(@ref.Steal());
949948

950-
// must decref our type
951-
Runtime.XDecref(StolenReference.DangerousFromPointer(type.DangerousGetAddress()));
949+
// must decref our type
950+
Runtime.XDecref(StolenReference.DangerousFromPointer(type.DangerousGetAddress()));
951+
}
952952
}
953953

954954
internal static FieldInfo? GetPyObjField(Type type) => type.GetField(PyObjName, PyObjFlags);

0 commit comments

Comments
 (0)