🌐 AI搜索 & 代理 主页
Skip to content
Prev Previous commit
Next Next commit
added a workaround for tp_clear implementations, that do not check, t…
…hat they are not the first in tp_clear's MRO

https://bugs.python.org/issue45266
  • Loading branch information
lostmsu committed Sep 22, 2021
commit 197689e07e5ce69dd73122371306cf4d69eb16ec
28 changes: 25 additions & 3 deletions src/runtime/classbase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -360,18 +360,40 @@ public static void tp_dealloc(IntPtr ob)

public static int tp_clear(IntPtr ob)
{
ManagedType self = GetManagedObject(ob);
if (GetManagedObject(ob) is { } self)
{
if (self.clearReentryGuard) return 0;

// workaround for https://bugs.python.org/issue45266
self.clearReentryGuard = true;

try
{
return ClearImpl(ob, self);
}
finally
{
self.clearReentryGuard = false;
}
}
else
{
return ClearImpl(ob, null);
}
}

static int ClearImpl(IntPtr ob, ManagedType self)
{
bool isTypeObject = Runtime.PyObject_TYPE(ob) == Runtime.PyCLRMetaType;
if (!isTypeObject)
{
ClearObjectDict(ob);

int baseClearResult = BaseUnmanagedClear(ob);
if (baseClearResult != 0)
{
return baseClearResult;
}

ClearObjectDict(ob);
}
if (self is not null) self.tpHandle = IntPtr.Zero;
return 0;
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/clrobject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ internal class CLRObject : ManagedType

internal CLRObject(object ob, IntPtr tp)
{
System.Diagnostics.Debug.Assert(tp != IntPtr.Zero);
Debug.Assert(tp != IntPtr.Zero);
IntPtr py = Runtime.PyType_GenericAlloc(tp, 0);

tpHandle = tp;
Expand Down
4 changes: 3 additions & 1 deletion src/runtime/managedtype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ internal enum TrackTypes
internal IntPtr pyHandle; // PyObject *
internal IntPtr tpHandle; // PyType *

internal bool clearReentryGuard;

internal BorrowedReference ObjectReference => new(pyHandle);
internal BorrowedReference TypeReference => new(tpHandle);

Expand Down Expand Up @@ -145,7 +147,7 @@ internal static bool IsInstanceOfManagedType(IntPtr ob)

internal static bool IsManagedType(BorrowedReference type)
{
var flags = (TypeFlags)Util.ReadCLong(type.DangerousGetAddress(), TypeOffset.tp_flags);
var flags = PyType.GetFlags(type);
return (flags & TypeFlags.HasClrInstance) != 0;
}

Expand Down
6 changes: 6 additions & 0 deletions src/runtime/pytype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ internal IntPtr GetSlot(TypeSlotID slot)
return Exceptions.ErrorCheckIfNull(result);
}

internal static TypeFlags GetFlags(BorrowedReference type)
{
Debug.Assert(TypeOffset.tp_flags > 0);
return (TypeFlags)Util.ReadCLong(type.DangerousGetAddress(), TypeOffset.tp_flags);
}

internal static BorrowedReference GetBase(BorrowedReference type)
{
Debug.Assert(IsType(type));
Expand Down