Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
7ed0c7a
WIP
lostmsu Oct 24, 2021
d6a853f
avoid generating and handling useless SerializationException when May…
lostmsu Oct 28, 2021
b0c25c1
finalizer does not attempt to finalize objects when runtime is shut down
lostmsu Oct 28, 2021
5ca474a
PyType Dict and MRO properties to assist debugging
lostmsu Oct 28, 2021
48078b3
WIP 2
lostmsu Oct 28, 2021
a624dd8
fixed PyObject disposal crashing when runtime is still finalizing
lostmsu Oct 29, 2021
e7ab071
arrays: use 64 bit indexing, and avoid first chance .NET exceptions o…
lostmsu Oct 29, 2021
cbe1dd2
refactored conditional ClassBase slot initialization
lostmsu Oct 29, 2021
d5f1c48
removed DisposePythonWrappersForClrTypes
lostmsu Oct 29, 2021
74d87c5
simplified outdated condition in ClassBase.tp_clear
lostmsu Oct 29, 2021
82d6c33
sprinkled a few DebuggerHidden to make debugging easier
lostmsu Oct 29, 2021
eeebcd7
fixed derived classes not inheriting slots correctly
lostmsu Oct 29, 2021
8ee8d3d
remove unused TypeManager._slotImpls
lostmsu Oct 29, 2021
1a4ada7
fixed TestRuntime not building in Release mode
lostmsu Oct 30, 2021
a610aa3
can't really clear managed references to Python objects from ManagedT…
lostmsu Oct 30, 2021
03f32cb
PythonException is serializable
lostmsu Oct 30, 2021
b1c9f5b
EventObject no longer used for static events. EventBinding is constru…
lostmsu Oct 30, 2021
cb4bb9a
use a special class to stub .NET types that no longer exist after a d…
lostmsu Nov 2, 2021
652f946
make EventHandlerCollection serializable
lostmsu Nov 2, 2021
84db670
fixed MaybeMemberInfo always failing for properties
lostmsu Nov 2, 2021
56fafe3
fixed construct_removed_class domain reload test case
lostmsu Nov 2, 2021
d33dcdd
domain reload test runner can run test by index
lostmsu Nov 2, 2021
b737e10
minor docs change
lostmsu Nov 2, 2021
d3e4fba
assert check in GetUnmanagedBaseType for null base
lostmsu Nov 2, 2021
e003e12
PythonEngine .Exec and .Eval no longer work with raw pointers
lostmsu Nov 9, 2021
d0a6f44
a few annotation to ease debugging
lostmsu Nov 9, 2021
e31f7ba
ensure Python types continue to exist when registered decoders for th…
lostmsu Nov 9, 2021
48c0dfc
GC-related WIP
lostmsu Nov 9, 2021
cb58147
merge latest changes from upstream
lostmsu Nov 23, 2021
2fdbf0e
added TraceAlloc solution configuration
lostmsu Nov 24, 2021
a8ef06c
fixed sending PyObject across domain boundary
lostmsu Nov 24, 2021
7167229
fixed accidental premature disposal of Runtime.PyNone
lostmsu Nov 24, 2021
ab11fa2
made freeing GCHandles more robust
lostmsu Nov 24, 2021
7a4daeb
removed bad assert in generated constructor for derived classes
lostmsu Nov 24, 2021
e422367
fixed __pyobj__ access
lostmsu Nov 24, 2021
a74ea86
minor
lostmsu Nov 24, 2021
0325a8c
fixed Python derived types trying to double-free GCHandle when collec…
lostmsu Nov 24, 2021
85fab3b
reinstate collection assert on shutdown from Python
lostmsu Nov 24, 2021
932fce2
fixed crash when Python derived class instances survive past early sh…
lostmsu Nov 24, 2021
c2e207a
delay nulling GC handles of reflected instances until the last moment…
lostmsu Nov 24, 2021
c8f0f09
fixed assert in XDecref in case _Py_IsFinalizing is not present
lostmsu Nov 24, 2021
e269cf0
when initialized from Python, reset slots implemented in CLR: CLR mig…
lostmsu Nov 25, 2021
d7d5cb7
fixed minor warnings
lostmsu Nov 25, 2021
d6edace
fixed line endings in intern_.cs
lostmsu Nov 25, 2021
a86994f
use NonCopyableAnalyzer 0.7.0-m05
lostmsu Nov 25, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fixed sending PyObject across domain boundary
removed debug code, that ensured Python GC list integrity
  • Loading branch information
lostmsu committed Nov 24, 2021
commit a8ef06c5ff76573a402ee53d2a3f56a4799d3ec2
15 changes: 0 additions & 15 deletions src/embed_tests/TestRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,6 @@ public static void Py_IsInitializedValue()
Assert.AreEqual(0, Runtime.Runtime.Py_IsInitialized());
}

[Test]
public static void IterAcrossRuns()
{
Runtime.Runtime.Py_Initialize();
BorrowedReference builtins = Runtime.Runtime.PyEval_GetBuiltins();
BorrowedReference iter = Runtime.Runtime.PyDict_GetItemString(builtins, "iter");

using var ownedIter = new NewReference(iter);
Runtime.Runtime.Py_Finalize();

Runtime.Runtime.Py_Initialize();
ownedIter.Dispose();
Runtime.Runtime.Py_Finalize();
}

[Test]
public static void RefCountTest()
{
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/ReflectedClrType.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.Runtime.Serialization;

using static Python.Runtime.PythonException;

Expand All @@ -10,6 +11,7 @@ internal sealed class ReflectedClrType : PyType
{
private ReflectedClrType(StolenReference reference) : base(reference, prevalidated: true) { }
internal ReflectedClrType(ReflectedClrType original) : base(original, prevalidated: true) { }
ReflectedClrType(SerializationInfo info, StreamingContext context) : base(info, context) { }

internal ClassBase Impl => (ClassBase)ManagedType.GetManagedObject(this)!;

Expand Down
4 changes: 0 additions & 4 deletions src/runtime/classbase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,6 @@ public static NewReference tp_repr(BorrowedReference ob)
/// </summary>
public static void tp_dealloc(NewReference lastRef)
{
Runtime.PyGC_ValidateLists();
Runtime.PyObject_GC_UnTrack(lastRef.Borrow());

CallClear(lastRef.Borrow());
Expand All @@ -347,12 +346,10 @@ public static void tp_dealloc(NewReference lastRef)
Debug.Assert(deleted);

DecrefTypeAndFree(lastRef.Steal());
Runtime.PyGC_ValidateLists();
}

public static int tp_clear(BorrowedReference ob)
{
Runtime.PyGC_ValidateLists();
GCHandle? gcHandle = TryGetGCHandle(ob);
gcHandle?.Free();

Expand All @@ -363,7 +360,6 @@ public static int tp_clear(BorrowedReference ob)
}

ClearObjectDict(ob);
Runtime.PyGC_ValidateLists();
return 0;
}

Expand Down
2 changes: 0 additions & 2 deletions src/runtime/classderived.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ internal ClassDerivedObject(Type tp) : base(tp)

public new static void tp_dealloc(NewReference ob)
{
Runtime.PyGC_ValidateLists();
var self = (CLRObject)GetManagedObject(ob.Borrow())!;

// don't let the python GC destroy this object
Expand All @@ -83,7 +82,6 @@ internal ClassDerivedObject(Type tp) : base(tp)
GCHandle gc = GCHandle.Alloc(self, GCHandleType.Weak);
SetGCHandle(ob.Borrow(), gc);
oldHandle.Free();
Runtime.PyGC_ValidateLists();
}

/// <summary>
Expand Down
4 changes: 0 additions & 4 deletions src/runtime/constructorbinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,7 @@ public static int tp_traverse(BorrowedReference ob, IntPtr visit, IntPtr arg)
var self = (ConstructorBinding?)GetManagedObject(ob);
if (self is null) return 0;

Runtime.PyGC_ValidateLists();
int res = PyVisit(self.typeToCreate, visit, arg);
Runtime.PyGC_ValidateLists();
return res;
}
}
Expand Down Expand Up @@ -237,9 +235,7 @@ public static int tp_traverse(BorrowedReference ob, IntPtr visit, IntPtr arg)
var self = (BoundContructor?)GetManagedObject(ob);
if (self is null) return 0;

Runtime.PyGC_ValidateLists();
int res = PyVisit(self.typeToCreate, visit, arg);
Runtime.PyGC_ValidateLists();
return res;
}
}
Expand Down
4 changes: 0 additions & 4 deletions src/runtime/extensiontype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ public static int tp_setattro(BorrowedReference ob, BorrowedReference key, Borro

public unsafe static void tp_dealloc(NewReference lastRef)
{
Runtime.PyGC_ValidateLists();
Runtime.PyObject_GC_UnTrack(lastRef.Borrow());

tp_clear(lastRef.Borrow());
Expand All @@ -86,18 +85,15 @@ public unsafe static void tp_dealloc(NewReference lastRef)

// we must decref our type: https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_dealloc
DecrefTypeAndFree(lastRef.Steal());
Runtime.PyGC_ValidateLists();
}

public static int tp_clear(BorrowedReference ob)
{
Runtime.PyGC_ValidateLists();
GCHandle? gcHandle = TryGetGCHandle(ob);
gcHandle?.Free();
if (gcHandle is not null) SetGCHandle(ob, default);

int res = ClassBase.BaseUnmanagedClear(ob);
Runtime.PyGC_ValidateLists();
return res;
}

Expand Down
37 changes: 23 additions & 14 deletions src/runtime/finalizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,19 +122,30 @@ internal List<IntPtr> GetCollectedObjects()
return _objQueue.Select(o => o.PyObj).ToList();
}

internal void AddFinalizedObject(ref IntPtr obj, int run)
internal void AddFinalizedObject(ref IntPtr obj, int run
#if TRACE_ALLOC
, StackTrace stackTrace
#endif
)
{
Debug.Assert(obj != IntPtr.Zero);
if (!Enable)
{
return;
}

Debug.Assert(Runtime.Refcount(new BorrowedReference(obj)) > 0);

#if FINALIZER_CHECK
lock (_queueLock)
#endif
{
this._objQueue.Enqueue(new PendingFinalization { PyObj = obj, RuntimeRun = run });
this._objQueue.Enqueue(new PendingFinalization {
PyObj = obj, RuntimeRun = run,
#if TRACE_ALLOC
StackTrace = stackTrace.ToString(),
#endif
});
}
obj = IntPtr.Zero;
}
Expand Down Expand Up @@ -165,10 +176,12 @@ internal static void Shutdown()
Instance.started = false;
}

private void DisposeAll()
internal nint DisposeAll()
{
if (_objQueue.IsEmpty && _derivedQueue.IsEmpty)
return;
return 0;

nint collected = 0;

BeforeCollect?.Invoke(this, new CollectArgs()
{
Expand Down Expand Up @@ -200,16 +213,8 @@ private void DisposeAll()
}

IntPtr copyForException = obj.PyObj;
Runtime.PyGC_ValidateLists();
var @ref = new BorrowedReference(obj.PyObj);
nint refs = Runtime.Refcount(@ref);
var type = Runtime.PyObject_TYPE(@ref);
string typeName = Runtime.ToString(type);
if (typeName == "<class 'clr.interop.PyErr'>")
{

}
Runtime.XDecref(StolenReference.Take(ref obj.PyObj));
collected++;
try
{
Runtime.CheckExceptionOccurred();
Expand All @@ -218,7 +223,6 @@ private void DisposeAll()
{
HandleFinalizationException(obj.PyObj, e);
}
Runtime.PyGC_ValidateLists();
}

while (!_derivedQueue.IsEmpty)
Expand All @@ -241,6 +245,7 @@ private void DisposeAll()
// matches correspdonging PyObject_GC_UnTrack
// in ClassDerivedObject.tp_dealloc
Runtime.PyObject_GC_Del(@ref.Steal());
collected++;

gcHandle.Free();
}
Expand All @@ -252,6 +257,7 @@ private void DisposeAll()
Runtime.PyErr_Restore(errType.StealNullable(), errVal.StealNullable(), traceback.StealNullable());
}
}
return collected;
}

void HandleFinalizationException(IntPtr obj, Exception cause)
Expand Down Expand Up @@ -341,6 +347,9 @@ struct PendingFinalization
{
public IntPtr PyObj;
public int RuntimeRun;
#if TRACE_ALLOC
public string StackTrace;
#endif
}

public class FinalizationException : Exception
Expand Down
2 changes: 0 additions & 2 deletions src/runtime/metatype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@ public static NewReference mp_subscript(BorrowedReference tp, BorrowedReference
/// </summary>
public static void tp_dealloc(NewReference lastRef)
{
Runtime.PyGC_ValidateLists();
// Fix this when we dont cheat on the handle for subclasses!

var flags = PyType.GetFlags(lastRef.Borrow());
Expand Down Expand Up @@ -318,7 +317,6 @@ public static void tp_dealloc(NewReference lastRef)
// We must decref our type.
// type_dealloc from PyType will use it to get tp_free so we must keep the value
Runtime.XDecref(StolenReference.DangerousFromPointer(op.DangerousGetAddress()));
Runtime.PyGC_ValidateLists();
}

private static NewReference DoInstanceCheck(BorrowedReference tp, BorrowedReference args, bool checkType)
Expand Down
4 changes: 4 additions & 0 deletions src/runtime/module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Linq;
using System.Collections.Generic;
using System.Dynamic;
using System.Runtime.Serialization;

namespace Python.Runtime
{
Expand Down Expand Up @@ -42,6 +43,9 @@ internal PyModule(in StolenReference reference) : base(reference)
}
}

protected PyModule(SerializationInfo info, StreamingContext context)
: base(info, context) { }

private void InitializeBuiltins()
{
int res = Runtime.PyDict_SetItem(
Expand Down
4 changes: 0 additions & 4 deletions src/runtime/moduleobject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -323,16 +323,12 @@ public static int tp_traverse(BorrowedReference ob, IntPtr visit, IntPtr arg)
var self = (ModuleObject?)GetManagedObject(ob);
if (self is null) return 0;

Runtime.PyGC_ValidateLists();
Debug.Assert(self.dict == GetObjectDict(ob));
int res = PyVisit(self.dict, visit, arg);
Runtime.PyGC_ValidateLists();
if (res != 0) return res;
foreach (var attr in self.cache.Values)
{
Runtime.PyGC_ValidateLists();
res = PyVisit(attr, visit, arg);
Runtime.PyGC_ValidateLists();
if (res != 0) return res;
}
return 0;
Expand Down
6 changes: 5 additions & 1 deletion src/runtime/pybuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,11 @@ private void Dispose(bool disposing)

if (_view.obj != IntPtr.Zero)
{
Finalizer.Instance.AddFinalizedObject(ref _view.obj, _exporter.run);
Finalizer.Instance.AddFinalizedObject(ref _view.obj, _exporter.run
#if TRACE_ALLOC
, _exporter.Traceback
#endif
);
}

Dispose(false);
Expand Down
4 changes: 4 additions & 0 deletions src/runtime/pydict.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Runtime.Serialization;

namespace Python.Runtime
{
Expand Down Expand Up @@ -33,6 +34,9 @@ public PyDict() : base(Runtime.PyDict_New().StealOrThrow()) { }
}
}

protected PyDict(SerializationInfo info, StreamingContext context)
: base(info, context) { }


/// <summary>
/// IsDictType Method
Expand Down
4 changes: 4 additions & 0 deletions src/runtime/pyfloat.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Runtime.Serialization;

namespace Python.Runtime
{
Expand Down Expand Up @@ -70,6 +71,9 @@ public PyFloat(string value) : base(FromString(value))
{
}

protected PyFloat(SerializationInfo info, StreamingContext context)
: base(info, context) { }


/// <summary>
/// IsFloatType Method
Expand Down
4 changes: 4 additions & 0 deletions src/runtime/pyint.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Runtime.Serialization;

namespace Python.Runtime
{
Expand Down Expand Up @@ -134,6 +135,9 @@ public PyInt(string value) : base(Runtime.PyLong_FromString(value, 0).StealOrThr
{
}

protected PyInt(SerializationInfo info, StreamingContext context)
: base(info, context) { }


/// <summary>
/// IsIntType Method
Expand Down
13 changes: 13 additions & 0 deletions src/runtime/pyiter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace Python.Runtime
{
Expand Down Expand Up @@ -89,5 +90,17 @@ public void Reset()

public PyObject Current => _current ?? throw new InvalidOperationException();
object System.Collections.IEnumerator.Current => Current;

protected PyIter(SerializationInfo info, StreamingContext context)
: base(info, context)
{
_current = (PyObject?)info.GetValue("c", typeof(PyObject));
}

protected override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("c", _current);
}
}
}
3 changes: 3 additions & 0 deletions src/runtime/pyiterable.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace Python.Runtime
{
Expand All @@ -9,6 +10,8 @@ public class PyIterable : PyObject, IEnumerable<PyObject>
{
internal PyIterable(BorrowedReference reference) : base(reference) { }
internal PyIterable(in StolenReference reference) : base(reference) { }
protected PyIterable(SerializationInfo info, StreamingContext context)
: base(info, context) { }

/// <summary>
/// Creates new instance from an existing object.
Expand Down
Loading