10000 added a workaround for tp_clear implementations, that do not check, t… · pythonnet/pythonnet@197689e · GitHub
[go: up one dir, main page]

Skip to content

Commit 197689e

Browse files
committed 10000
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 197689e

File tree

4 files changed

+35
-5
lines changed

4 files changed

+35
-5
lines changed

src/runtime/classbase.cs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,18 +360,40 @@ public static void tp_dealloc(IntPtr ob)
360360

361361
public static int tp_clear(IntPtr ob)
362362
{
363-
ManagedType self = GetManagedObject(ob);
363+
if (GetManagedObject(ob) is { } self)
364+
{
365+
if (self.clearReentryGuard) return 0;
366+
367+
// workaround for https://bugs.python.org/issue45266
368+
self.clearReentryGuard = true;
369+
370+
try
371+
{
372+
return ClearImpl(ob, self);
373+
}
374+
finally
375+
{
376+
self.clearReentryGuard = false;
377+
}
378+
}
379+
else
380+
{
381+
return ClearImpl(ob, null);
382+
}
383+
}
364384

385+
static int ClearImpl(IntPtr ob, ManagedType self)
386+
{
365387
bool isTypeObject = Runtime.PyObject_TYPE(ob) == Runtime.PyCLRMetaType;
366388
if (!isTypeObject)
367389
{
368-
ClearObjectDict(ob);
369-
370390
int baseClearResult = BaseUnmanagedClear(ob);
371391
if (baseClearResult != 0)
372392
{
373393
return baseClearResult;
374394
}
395+
396+
ClearObjectDict(ob);
375397
}
376398
if (self is not null) self.tpHandle = IntPtr.Zero;
377399
return 0;

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)
0