diff --git a/src/runtime/constructorbinding.cs b/src/runtime/constructorbinding.cs
index ab4a7af0a..9ac1adc0f 100644
--- a/src/runtime/constructorbinding.cs
+++ b/src/runtime/constructorbinding.cs
@@ -149,17 +149,10 @@ public static IntPtr tp_repr(IntPtr ob)
return self.repr;
}
- protected override void Dealloc()
+ protected override void Clear()
{
Runtime.Py_CLEAR(ref this.repr);
- base.Dealloc();
- }
-
- public static int tp_clear(IntPtr ob)
- {
- var self = (ConstructorBinding)GetManagedObject(ob);
- Runtime.Py_CLEAR(ref self.repr);
- return 0;
+ base.Clear();
}
public static int tp_traverse(IntPtr ob, IntPtr visit, IntPtr arg)
@@ -248,17 +241,10 @@ public static IntPtr tp_repr(IntPtr ob)
return self.repr;
}
- protected override void Dealloc()
+ protected override void Clear()
{
Runtime.Py_CLEAR(ref this.repr);
- base.Dealloc();
- }
-
- public static int tp_clear(IntPtr ob)
- {
- var self = (BoundContructor)GetManagedObject(ob);
- Runtime.Py_CLEAR(ref self.repr);
- return 0;
+ base.Clear();
}
public static int tp_traverse(IntPtr ob, IntPtr visit, IntPtr arg)
diff --git a/src/runtime/eventbinding.cs b/src/runtime/eventbinding.cs
index 60b9bba92..65c8fdccf 100644
--- a/src/runtime/eventbinding.cs
+++ b/src/runtime/eventbinding.cs
@@ -103,17 +103,10 @@ public static IntPtr tp_repr(IntPtr ob)
return Runtime.PyString_FromString(s);
}
- protected override void Dealloc()
+ protected override void Clear()
{
Runtime.Py_CLEAR(ref this.target);
- base.Dealloc();
- }
-
- public static int tp_clear(IntPtr ob)
- {
- var self = (EventBinding)GetManagedObject(ob);
- Runtime.Py_CLEAR(ref self.target);
- return 0;
+ base.Clear();
}
}
}
diff --git a/src/runtime/eventobject.cs b/src/runtime/eventobject.cs
index e9bd98821..941bbdf46 100644
--- a/src/runtime/eventobject.cs
+++ b/src/runtime/eventobject.cs
@@ -198,14 +198,14 @@ public static IntPtr tp_repr(IntPtr ob)
}
- protected override void Dealloc()
+ protected override void Clear()
{
if (this.unbound is not null)
{
Runtime.XDecref(this.unbound.pyHandle);
this.unbound = null;
}
- base.Dealloc();
+ base.Clear();
}
}
diff --git a/src/runtime/extensiontype.cs b/src/runtime/extensiontype.cs
index db9eb0f72..78df805ee 100644
--- a/src/runtime/extensiontype.cs
+++ b/src/runtime/extensiontype.cs
@@ -56,10 +56,21 @@ void SetupGc ()
protected virtual void Dealloc()
{
- ClearObjectDict(this.pyHandle);
+ var type = Runtime.PyObject_TYPE(this.ObjectReference);
Runtime.PyObject_GC_Del(this.pyHandle);
- // Not necessary for decref of `tpHandle`.
+ // Not necessary for decref of `tpHandle` - it is borrowed
+
this.FreeGCHandle();
+
+ // we must decref our type: https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_dealloc
+ Runtime.XDecref(type.DangerousGetAddress());
+ }
+
+ /// DecRefs and nulls any fields pointing back to Python
+ protected virtual void Clear()
+ {
+ ClearObjectDict(this.pyHandle);
+ // Not necessary for decref of `tpHandle` - it is borrowed
}
///
@@ -88,17 +99,22 @@ public static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val)
}
- ///
- /// Default dealloc implementation.
- ///
public static void tp_dealloc(IntPtr ob)
{
// Clean up a Python instance of this extension type. This
// frees the allocated Python object and decrefs the type.
var self = (ExtensionType)GetManagedObject(ob);
+ self?.Clear();
self?.Dealloc();
}
+ public static int tp_clear(IntPtr ob)
+ {
+ var self = (ExtensionType)GetManagedObject(ob);
+ self?.Clear();
+ return 0;
+ }
+
protected override void OnLoad(InterDomainContext context)
{
base.OnLoad(context);
diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs
index 783717189..c1e729f9e 100644
--- a/src/runtime/methodbinding.cs
+++ b/src/runtime/methodbinding.cs
@@ -229,23 +229,11 @@ public static IntPtr tp_repr(IntPtr ob)
return Runtime.PyString_FromString($"<{type} method '{name}'>");
}
- private void ClearMembers()
+ protected override void Clear()
{
- Runtime.Py_CLEAR(ref target);
- Runtime.Py_CLEAR(ref targetType);
- }
-
- protected override void Dealloc()
- {
- this.ClearMembers();
- base.Dealloc();
- }
-
- public static int tp_clear(IntPtr ob)
- {
- var self = (MethodBinding)GetManagedObject(ob);
- self.ClearMembers();
- return 0;
+ Runtime.Py_CLEAR(ref this.target);
+ Runtime.Py_CLEAR(ref this.targetType);
+ base.Clear();
}
protected override void OnSave(InterDomainContext context)
diff --git a/src/runtime/methodobject.cs b/src/runtime/methodobject.cs
index 5fa965f1b..2787ec999 100644
--- a/src/runtime/methodobject.cs
+++ b/src/runtime/methodobject.cs
@@ -200,29 +200,17 @@ public static IntPtr tp_repr(IntPtr ob)
return Runtime.PyString_FromString($"");
}
- private void ClearMembers()
+ protected override void Clear()
{
- Runtime.Py_CLEAR(ref doc);
- if (unbound != null)
+ Runtime.Py_CLEAR(ref this.doc);
+ if (this.unbound != null)
{
- Runtime.XDecref(unbound.pyHandle);
- unbound = null;
+ Runtime.XDecref(this.unbound.pyHandle);
+ this.unbound = null;
}
- }
- protected override void Dealloc()
- {
- this.ClearMembers();
ClearObjectDict(this.pyHandle);
- base.Dealloc();
- }
-
- public static int tp_clear(IntPtr ob)
- {
- var self = (MethodObject)GetManagedObject(ob);
- self.ClearMembers();
- ClearObjectDict(ob);
- return 0;
+ base.Clear();
}
protected override void OnSave(InterDomainContext context)
diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs
index 1ab014c2a..606fa7be9 100644
--- a/src/runtime/moduleobject.cs
+++ b/src/runtime/moduleobject.cs
@@ -295,12 +295,6 @@ public static IntPtr tp_repr(IntPtr ob)
return Runtime.PyString_FromString($"");
}
- protected override void Dealloc()
- {
- tp_clear(this.pyHandle);
- base.Dealloc();
- }
-
public static int tp_traverse(IntPtr ob, IntPtr visit, IntPtr arg)
{
var self = (ModuleObject)GetManagedObject(ob);
@@ -314,17 +308,16 @@ public static int tp_traverse(IntPtr ob, IntPtr visit, IntPtr arg)
return 0;
}
- public static int tp_clear(IntPtr ob)
+ protected override void Clear()
{
- var self = (ModuleObject)GetManagedObject(ob);
- Runtime.Py_CLEAR(ref self.dict);
- ClearObjectDict(ob);
- foreach (var attr in self.cache.Values)
+ Runtime.Py_CLEAR(ref this.dict);
+ ClearObjectDict(this.pyHandle);
+ foreach (var attr in this.cache.Values)
{
Runtime.XDecref(attr.pyHandle);
}
- self.cache.Clear();
- return 0;
+ this.cache.Clear();
+ base.Clear();
}
protected override void OnSave(InterDomainContext context)
diff --git a/src/runtime/overload.cs b/src/runtime/overload.cs
index 48fabca4a..8222dc136 100644
--- a/src/runtime/overload.cs
+++ b/src/runtime/overload.cs
@@ -58,10 +58,10 @@ public static IntPtr tp_repr(IntPtr op)
return doc;
}
- protected override void Dealloc()
+ protected override void Clear()
{
Runtime.Py_CLEAR(ref this.target);
- base.Dealloc();
+ base.Clear();
}
}
}