Skip to content

Commit bc137bb

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 bc137bb

File tree

4 files changed

+31
-12
lines changed

4 files changed

+31
-12
lines changed

src/runtime/classbase.cs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -360,21 +360,33 @@ public static void tp_dealloc(IntPtr ob)
360360

361361
public static int tp_clear(IntPtr ob)
362362
{
363-
ManagedType self = GetManagedObject(ob);
363+
var self = (CLRObject)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;
369366

370-
int baseClearResult = BaseUnmanagedClear(ob);
371-
if (baseClearResult != 0)
367+
// workaround for https://bugs.python.org/issue45266
368+
self.clearReentryGuard = true;
369+
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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ namespace Python.Runtime
99
internal class CLRObject : ManagedType
1010
{
1111
internal object inst;
12+
internal bool clearReentryGuard;
1213

1314
internal CLRObject(object ob, IntPtr tp)
1415
{
15-
System.Diagnostics.Debug.Assert(tp != IntPtr.Zero);
16+
Debug.Assert(tp != IntPtr.Zero);
1617
IntPtr py = Runtime.PyType_GenericAlloc(tp, 0);
1718

1819
tpHandle = tp;

src/runtime/managedtype.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ internal static bool IsInstanceOfManagedType(IntPtr ob)
145145

146146
internal static bool IsManagedType(BorrowedReference type)
147147
{
148-
var flags = (TypeFlags)Util.ReadCLong(type.DangerousGetAddress(), TypeOffset.tp_flags);
148+
var flags = PyType.GetFlags(type);
149149
return (flags & TypeFlags.HasClrInstance) != 0;
150150
}
151151

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)