Skip to content

Commit 7fa3e8e

Browse files
committed
clear weak reference list when an extension type is destroyed
According to official documentation for defining extension types, if they are to support weak references, they must clear weak reference list associated with the instance in tp_clear. Extension types were missed in pythonnet#1758 ( 50da522 )
1 parent 50da522 commit 7fa3e8e

3 files changed

Lines changed: 44 additions & 0 deletions

File tree

src/embed_tests/ExtensionTypes.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
3+
using NUnit.Framework;
4+
5+
using Python.Runtime;
6+
7+
namespace Python.EmbeddingTest;
8+
9+
public class ExtensionTypes
10+
{
11+
[OneTimeSetUp]
12+
public void SetUp()
13+
{
14+
PythonEngine.Initialize();
15+
}
16+
17+
[OneTimeTearDown]
18+
public void Dispose()
19+
{
20+
PythonEngine.Shutdown();
21+
}
22+
23+
[Test]
24+
public void WeakrefIsNone_AfterBoundMethodIsGone()
25+
{
26+
using var makeref = Py.Import("weakref").GetAttr("ref");
27+
var boundMethod = new UriBuilder().ToPython().GetAttr(nameof(UriBuilder.GetHashCode));
28+
var weakref = makeref.Invoke(boundMethod);
29+
boundMethod.Dispose();
30+
Assert.IsTrue(weakref.Invoke().IsNone());
31+
}
32+
}

src/runtime/Types/ExtensionType.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ public unsafe static void tp_dealloc(NewReference lastRef)
8686

8787
public static int tp_clear(BorrowedReference ob)
8888
{
89+
var weakrefs = Runtime.PyObject_GetWeakRefList(ob);
90+
if (weakrefs != null)
91+
{
92+
Runtime.PyObject_ClearWeakRefs(ob);
93+
}
94+
8995
if (TryFreeGCHandle(ob))
9096
{
9197
bool deleted = loadedExtensions.Remove(ob.DangerousGetAddress());

src/runtime/Types/MetaType.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,12 @@ public static NewReference mp_subscript(BorrowedReference tp, BorrowedReference
273273
/// </summary>
274274
public static void tp_dealloc(NewReference lastRef)
275275
{
276+
var weakrefs = Runtime.PyObject_GetWeakRefList(lastRef.Borrow());
277+
if (weakrefs != null)
278+
{
279+
Runtime.PyObject_ClearWeakRefs(lastRef.Borrow());
280+
}
281+
276282
// Fix this when we dont cheat on the handle for subclasses!
277283

278284
var flags = PyType.GetFlags(lastRef.Borrow());

0 commit comments

Comments
 (0)