8000 Del SlotsHolder from tp_dict when shutting down · pythonnet/pythonnet@2a88be4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2a88be4

Browse files
committed
Del SlotsHolder from tp_dict when shutting down
1 parent 7db724e commit 2a88be4

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

src/runtime/metatype.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ public static void Release()
2828
{
2929
SlotsHolder.ReleaseTypeSlots(PyCLRMetaType);
3030
}
31-
Runtime.XDecref(PyCLRMetaType);
31+
// FIXME: Crash on .netcore if decref PyCLRMetaType
32+
// Runtime.XDecref(PyCLRMetaType);
3233
PyCLRMetaType = IntPtr.Zero;
3334
}
3435

@@ -275,6 +276,7 @@ private static IntPtr DoInstanceCheck(IntPtr tp, IntPtr args, bool checkType)
275276
return Runtime.PyFalse;
276277
}
277278

279+
Runtime.XIncref(args);
278280
using (var argsObj = new PyList(args))
279281
{
280282
if (argsObj.Length() != 1)

src/runtime/runtime.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ internal static void Initialize(bool initSigs = false, bool softShutdown = false
225225
SetPyMember(ref PyWrapperDescriptorType, PyObject_Type(op));
226226
XDecref(op);
227227

228+
SetPyMember(ref PySuper_Type, PyObject_GetAttrString(builtins, "super"));
229+
228230
op = PyObject_GetAttrString(builtins, "KeyError");
229231
SetPyMember(ref PyExc_KeyError, op);
230232

@@ -481,11 +483,13 @@ private static void MoveClrInstancesOnwershipToPython()
481483
var objs = ManagedType.GetManagedObjects();
482484
foreach (var obj in copyObjs)
483485
{
484-
if (objs.Contains(obj))
486+
if (!objs.Contains(obj))
485487
{
486488
continue;
487489
}
488490
obj.TypeClear();
491+
// obj's tp_type will degenerate to a pure Python type after TypeManager.RemoveTypes(),
492+
// thus just be safe to give it back to GC chain.
489493
PyObject_GC_Track(obj.pyHandle);
490494
obj.gcHandle.Free();
491495
obj.gcHandle = new GCHandle();
@@ -502,6 +506,7 @@ private static void MoveClrInstancesOnwershipToPython()
502506
internal static IntPtr PyModuleType;
503507
internal static IntPtr PyClassType;
504508
internal static IntPtr PyInstanceType;
509+
internal static IntPtr PySuper_Type;
505510
internal static IntPtr PyCLRMetaType;
506511
internal static IntPtr PyMethodType;
507512
internal static IntPtr PyWrapperDescriptorType;
@@ -895,6 +900,7 @@ public static extern int Py_Main(
895900
//====================================================================
896901

897902
/// <summary>
903+
/// Return value: Borrowed reference.
898904
/// A macro-like method to get the type of a Python object. This is
899905
/// designed to be lean and mean in IL &amp; avoid managed &lt;-&gt; unmanaged
900906
/// transitions. Note that this does not incref the type object.

src/runtime/typemanager.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -826,8 +826,8 @@ internal static void InitializeSlots(IntPtr type, Type impl, SlotsHolder slotsHo
826826
IntPtr ret1 = NativeCodePage + native.Return1;
827827
IntPtr ret0 = NativeCodePage + native.Return0;
828828

829-
InitializeSlot(type, ret0, "tp_traverse", canOverride);
830-
InitializeSlot(type, ret0, "tp_clear", canOverride);
829+
InitializeSlot(type, ret0, "tp_traverse", false);
830+
InitializeSlot(type, ret0, "tp_clear", false);
831831
}
832832
else
833833
{
@@ -968,6 +968,7 @@ class SlotsHolder
968968
private List<Delegate> _keepalive = new List<Delegate>();
969969
private Dictionary<int, Resetor> _customRestors = new Dictionary<int, Resetor>();
970970
private List<Action> _deallocators = new List<Action>();
971+
private bool _alredyReset = false;
971972

972973
/// <summary>
973974
/// Create slots holder for holding the delegate of slots and be able to reset them.
@@ -1021,10 +1022,22 @@ public static void ReleaseTypeSlots(IntPtr type)
10211022
}
10221023
var self = RecoverFromCapsule(capsule);
10231024
self.ResetSlots();
1025+
Runtime.XDecref(capsule);
1026+
1027+
IntPtr tp_dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
1028+
if (Runtime.PyDict_DelItemString(tp_dict, HolderKeyName) != 0)
1029+
{
1030+
throw new PythonException();
1031+
}
10241032
}
10251033

10261034
private void ResetSlots()
10271035
{
1036+
if (_alredyReset)
1037+
{
1038+
return;
1039+
}
1040+
_alredyReset = true;
10281041
IntPtr tp_name = Marshal.ReadIntPtr(_type, TypeOffset.tp_name);
10291042
string typeName = Marshal.PtrToStringAnsi(tp_name);
10301043
foreach (var offset in _slots.Keys)
@@ -1055,6 +1068,10 @@ private void ResetSlots()
10551068
IntPtr tp_base = Marshal.ReadIntPtr(_type, TypeOffset.tp_base);
10561069
Runtime.XDecref(tp_base);
10571070
Marshal.WriteIntPtr(_type, TypeOffset.tp_base, IntPtr.Zero);
1071+
1072+
IntPtr tp_bases = Marshal.ReadIntPtr(_type, TypeOffset.tp_bases);
1073+
Runtime.XDecref(tp_bases);
1074+
Marshal.WriteIntPtr(_type, TypeOffset.tp_bases, IntPtr.Zero);
10581075
}
10591076

10601077
private static void OnDestruct(IntPtr ob)
@@ -1088,6 +1105,11 @@ private static IntPtr GetDefaultSlot(int offset)
10881105
{
10891106
return IntPtr.Zero;
10901107
}
1108+
else if (offset == TypeOffset.tp_new)
1109+
{
1110+
// PyType_GenericNew
1111+
return Marshal.ReadIntPtr(Runtime.PySuper_Type, TypeOffset.tp_new);
1112+
}
10911113

10921114
return Marshal.ReadIntPtr(Runtime.PyTypeType, offset);
10931115
}

0 commit comments

Comments
 (0)
0