Skip to content

Commit 4e2d9f0

Browse files
committed
added a workaround for tp_clear implementations, that do not check, that they are not the first in tp_clear's MRO
https://bugs.python.org/issue45266
1 parent 6b20409 commit 4e2d9f0

File tree

4 files changed

+31
-11
lines changed

4 files changed

+31
-11
lines changed

src/runtime/classbase.cs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -362,19 +362,31 @@ public static int tp_clear(IntPtr ob)
362362
{
363363
ManagedType self = GetManagedObject(ob);
364364

365-
bool isTypeObject = Runtime.PyObject_TYPE(ob) == Runtime.PyCLRMetaType;
366-
if (!isTypeObject)
367-
{
368-
ClearObjectDict(ob);
365+
if (self.clearReentryGuard) return 0;
366+
367+
// workaround for https://bugs.python.org/issue45266
368+
self.clearReentryGuard = true;
369369

370-
int baseClearResult = BaseUnmanagedClear(ob);
371-
if (baseClearResult != 0)
370+
try
371+
{
372+
bool isTypeObject = Runtime.PyObject_TYPE(ob) == Runtime.PyCLRMetaType;
373+
if (!isTypeObject)
372374
{
373-
return baseClearResult;
375+
int baseClearResult = BaseUnmanagedClear(ob);
376+
if (baseClearResult != 0)
377+
{
378+
return baseClearResult;
379+
}
380+
381+
ClearObjectDict(ob);
374382
}
383+
if (self is not null) self.tpHandle = IntPtr.Zero;
384+
return 0;
385+
}
386+
finally
387+
{
388+
self.clearReentryGuard = false;
375389
}
376-
if (self is not null) self.tpHandle = IntPtr.Zero;
377-
return 0;
378390
}
379391

380392
static unsafe int BaseUnmanagedClear(IntPtr ob)

src/runtime/clrobject.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ internal class CLRObject : ManagedType
1212

1313
internal CLRObject(object ob, IntPtr tp)
1414
{
15-
System.Diagnostics.Debug.Assert(tp != IntPtr.Zero);
15+
Debug.Assert(tp != IntPtr.Zero);
1616
IntPtr py = Runtime.PyType_GenericAlloc(tp, 0);
1717

1818
tpHandle = tp;

src/runtime/managedtype.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ internal enum TrackTypes
2828
internal IntPtr pyHandle; // PyObject *
2929
internal IntPtr tpHandle; // PyType *
3030

31+
internal bool clearReentryGuard;
32+
3133
internal BorrowedReference ObjectReference => new(pyHandle);
3234
internal BorrowedReference TypeReference => new(tpHandle);
3335

@@ -145,7 +147,7 @@ internal static bool IsInstanceOfManagedType(IntPtr ob)
145147

146148
internal static bool IsManagedType(BorrowedReference type)
147149
{
148-
var flags = (TypeFlags)Util.ReadCLong(type.DangerousGetAddress(), TypeOffset.tp_flags);
150+
var flags = PyType.GetFlags(type);
149151
return (flags & TypeFlags.HasClrInstance) != 0;
150152
}
151153

src/runtime/pytype.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ internal IntPtr GetSlot(TypeSlotID slot)
103103
return Exceptions.ErrorCheckIfNull(result);
104104
}
105105

106+
internal static TypeFlags GetFlags(BorrowedReference type)
107+
{
108+
Debug.Assert(TypeOffset.tp_flags > 0);
109+
return (TypeFlags)Util.ReadCLong(type.DangerousGetAddress(), TypeOffset.tp_flags);
110+
}
111+
106112
internal static BorrowedReference GetBase(BorrowedReference type)
107113
{
108114
Debug.Assert(IsType(type));

0 commit comments

Comments
 (0)