Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4403d4f

Browse files
committed
Move tp_clear workaround to .NET
In Python 3.14, the objects __dict__ seems to already be halfdeconstructed, leading to crashes during garbage collection.Since gc in Python is single-threaded (I think :)), it shouldbe fine to have a single static for this. If that is not true,we can always use a thread-local instead.
1 parentf9b924b commit4403d4f

File tree

5 files changed

+13
-23
lines changed

5 files changed

+13
-23
lines changed

‎src/runtime/Native/PyIdentifier_.cs‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ static class PyIdentifier
1313
publicstaticBorrowedReference__doc__=>new(f__doc__);
1414
staticIntPtrf__class__;
1515
publicstaticBorrowedReference__class__=>new(f__class__);
16-
staticIntPtrf__clear_reentry_guard__;
17-
publicstaticBorrowedReference__clear_reentry_guard__=>new(f__clear_reentry_guard__);
1816
staticIntPtrf__module__;
1917
publicstaticBorrowedReference__module__=>new(f__module__);
2018
staticIntPtrf__file__;
@@ -51,7 +49,6 @@ static partial class InternString
5149
"__dict__",
5250
"__doc__",
5351
"__class__",
54-
"__clear_reentry_guard__",
5552
"__module__",
5653
"__file__",
5754
"__slots__",

‎src/runtime/Native/PyIdentifier_.tt‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
"__dict__",
88
"__doc__",
99
"__class__",
10-
"__clear_reentry_guard__",
1110
"__module__",
1211
"__file__",
1312
"__slots__",

‎src/runtime/Types/ClassBase.cs‎

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,11 @@ public static int tp_clear(BorrowedReference ob)
374374
return0;
375375
}
376376

377+
staticreadonlyHashSet<IntPtr>ClearVisited=new();
378+
377379
internalstaticunsafeintBaseUnmanagedClear(BorrowedReferenceob)
378380
{
381+
379382
vartype=Runtime.PyObject_TYPE(ob);
380383
varunmanagedBase=GetUnmanagedBaseType(type);
381384
varclearPtr=Util.ReadIntPtr(unmanagedBase,TypeOffset.tp_clear);
@@ -385,26 +388,21 @@ internal static unsafe int BaseUnmanagedClear(BorrowedReference ob)
385388
}
386389
varclear=(delegate* unmanaged[Cdecl]<BorrowedReference,int>)clearPtr;
387390

388-
boolusesSubtypeClear=clearPtr==TypeManager.subtype_clear;
389-
if(usesSubtypeClear)
391+
if(clearPtr==TypeManager.subtype_clear)
390392
{
391-
// workaround for https://bugs.python.org/issue45266 (subtype_clear)
392-
usingvardict=Runtime.PyObject_GenericGetDict(ob);
393-
if(Runtime.PyMapping_HasKey(dict.Borrow(),PyIdentifier.__clear_reentry_guard__)!=0)
393+
varaddr=ob.DangerousGetAddress();
394+
if(ClearVisited.Contains(addr))
394395
return0;
395396

396-
intres=Runtime.PyDict_SetItem(
397-
dict.Borrow(),
398-
PyIdentifier.__clear_reentry_guard__,
399-
Runtime.PyTrue
400-
);
401-
if(res!=0)returnres;
402-
403-
res=clear(ob);
404-
Runtime.PyDict_DelItem(dict.Borrow(),PyIdentifier.__clear_reentry_guard__);
397+
ClearVisited.Add(addr);
398+
intres=clear(ob);
399+
ClearVisited.Remove(addr);
405400
returnres;
406401
}
407-
returnclear(ob);
402+
else
403+
{
404+
returnclear(ob);
405+
}
408406
}
409407

410408
protectedoverrideDictionary<string,object?>OnSave(BorrowedReferenceob)

‎tests/test_method.py‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -942,7 +942,6 @@ def test_getting_generic_method_binding_does_not_leak_ref_count():
942942
refCount=sys.getrefcount(PlainOldClass().GenericMethod[str])
943943
assertrefCount==1
944944

945-
@pytest.mark.skipif(sys.version_info>= (3,14),reason="Test skipped on Python 3.14 and above")
946945
deftest_getting_generic_method_binding_does_not_leak_memory():
947946
"""Test that managed object is freed after calling generic method. Issue #691"""
948947

@@ -984,7 +983,6 @@ def test_getting_overloaded_method_binding_does_not_leak_ref_count():
984983
refCount=sys.getrefcount(PlainOldClass().OverloadedMethod.Overloads[int])
985984
assertrefCount==1
986985

987-
@pytest.mark.skipif(sys.version_info>= (3,14),reason="Test skipped on Python 3.14 and above")
988986
deftest_getting_overloaded_method_binding_does_not_leak_memory():
989987
"""Test that managed object is freed after calling overloaded method. Issue #691"""
990988

@@ -1027,7 +1025,6 @@ def test_getting_method_overloads_binding_does_not_leak_ref_count():
10271025
assertrefCount==1
10281026

10291027
@pytest.mark.xfail(reason="Fails locally, need to investigate later",strict=False)
1030-
@pytest.mark.skipif(sys.version_info>= (3,14),reason="Test skipped on Python 3.14 and above")
10311028
deftest_getting_method_overloads_binding_does_not_leak_memory():
10321029
"""Test that managed object is freed after calling overloaded method. Issue #691"""
10331030

‎tests/test_subclass.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,6 @@ def __init__(self, i, s):
304304
assertcalls[0][1]=="foo"
305305

306306
# regression test for https://github.com/pythonnet/pythonnet/issues/1565
307-
@pytest.mark.skipif(sys.version_info>= (3,14),reason="Test skipped on Python 3.14 and above")
308307
deftest_can_be_collected_by_gc():
309308
fromPython.TestimportBaseClass
310309

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp