Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
- Dmitriy Se ([@dmitriyse](https://github.com/dmitriyse))
- Félix Bourbonnais ([@BadSingleton](https://github.com/BadSingleton))
- Florian Treurniet ([@ftreurni](https://github.com/ftreurni))
- Frank Witscher ([@Frawak](https://github.com/Frawak))
- He-chien Tsai ([@t3476](https://github.com/t3476))
- Inna Wiesel ([@inna-w](https://github.com/inna-w))
- Ivan Cronyn ([@cronan](https://github.com/cronan))
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].

- Fixed RecursionError for reverse operators on C# operable types from python. See #2240
- Fixed probing for assemblies in `sys.path` failing when a path in `sys.path` has invalid characters. See #2376
- Fixed possible access violation exception on shutdown. See ([#1977][i1977])

## [3.0.3](https://github.com/pythonnet/pythonnet/releases/tag/v3.0.3) - 2023-10-11

Expand Down Expand Up @@ -970,3 +971,4 @@ This version improves performance on benchmarks significantly compared to 2.3.
[i1481]: https://github.com/pythonnet/pythonnet/issues/1481
[i1672]: https://github.com/pythonnet/pythonnet/pull/1672
[i2311]: https://github.com/pythonnet/pythonnet/issues/2311
[i1977]: https://github.com/pythonnet/pythonnet/issues/1977
8 changes: 4 additions & 4 deletions src/runtime/Finalizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ internal static void Shutdown()
Instance.started = false;
}

internal nint DisposeAll()
internal nint DisposeAll(bool disposeObj = true, bool disposeDerived = true, bool disposeBuffer = true)
{
if (_objQueue.IsEmpty && _derivedQueue.IsEmpty && _bufferQueue.IsEmpty)
return 0;
Expand All @@ -216,7 +216,7 @@ internal nint DisposeAll()

try
{
while (!_objQueue.IsEmpty)
if (disposeObj) while (!_objQueue.IsEmpty)
{
if (!_objQueue.TryDequeue(out var obj))
continue;
Expand All @@ -240,7 +240,7 @@ internal nint DisposeAll()
}
}

while (!_derivedQueue.IsEmpty)
if (disposeDerived) while (!_derivedQueue.IsEmpty)
{
if (!_derivedQueue.TryDequeue(out var derived))
continue;
Expand All @@ -258,7 +258,7 @@ internal nint DisposeAll()
collected++;
}

while (!_bufferQueue.IsEmpty)
if (disposeBuffer) while (!_bufferQueue.IsEmpty)
{
if (!_bufferQueue.TryDequeue(out var buffer))
continue;
Expand Down
15 changes: 11 additions & 4 deletions src/runtime/Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ internal static void Initialize(bool initSigs = false)
ClassManager.Reset();
ClassDerivedObject.Reset();
TypeManager.Initialize();
CLRObject.creationBlocked = false;
_typesInitialized = true;

// Initialize modules that depend on the runtime class.
Expand Down Expand Up @@ -278,6 +279,9 @@ internal static void Shutdown()
ClearClrModules();
RemoveClrRootModule();

TryCollectingGarbage(MaxCollectRetriesOnShutdown, forceBreakLoops: true,
obj: true, derived: false, buffer: false);

NullGCHandles(ExtensionType.loadedExtensions);
ClassManager.RemoveClasses();
TypeManager.RemoveTypes();
Expand All @@ -295,8 +299,7 @@ internal static void Shutdown()
PyObjectConversions.Reset();

PyGC_Collect();
bool everythingSeemsCollected = TryCollectingGarbage(MaxCollectRetriesOnShutdown,
forceBreakLoops: true);
bool everythingSeemsCollected = TryCollectingGarbage(MaxCollectRetriesOnShutdown);
Debug.Assert(everythingSeemsCollected);

Finalizer.Shutdown();
Expand Down Expand Up @@ -328,7 +331,8 @@ internal static void Shutdown()

const int MaxCollectRetriesOnShutdown = 20;
internal static int _collected;
static bool TryCollectingGarbage(int runs, bool forceBreakLoops)
static bool TryCollectingGarbage(int runs, bool forceBreakLoops,
bool obj = true, bool derived = true, bool buffer = true)
{
if (runs <= 0) throw new ArgumentOutOfRangeException(nameof(runs));

Expand All @@ -341,7 +345,9 @@ static bool TryCollectingGarbage(int runs, bool forceBreakLoops)
GC.Collect();
GC.WaitForPendingFinalizers();
pyCollected += PyGC_Collect();
pyCollected += Finalizer.Instance.DisposeAll();
pyCollected += Finalizer.Instance.DisposeAll(disposeObj: obj,
disposeDerived: derived,
disposeBuffer: buffer);
}
if (Volatile.Read(ref _collected) == 0 && pyCollected == 0)
{
Expand All @@ -351,6 +357,7 @@ static bool TryCollectingGarbage(int runs, bool forceBreakLoops)
{
NullGCHandles(CLRObject.reflectedObjects);
CLRObject.reflectedObjects.Clear();
CLRObject.creationBlocked = true;
}
}
return false;
Expand Down
8 changes: 8 additions & 0 deletions src/runtime/Types/ClrObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@ internal sealed class CLRObject : ManagedType
{
internal readonly object inst;

internal static bool creationBlocked = false;

// "borrowed" references
internal static readonly HashSet<IntPtr> reflectedObjects = new();
static NewReference Create(object ob, BorrowedReference tp)
{
if (creationBlocked)
throw new InvalidOperationException("Reflected objects should not be created anymore.");

Debug.Assert(tp != null);
var py = Runtime.PyType_GenericAlloc(tp, 0);

Expand Down Expand Up @@ -61,6 +66,9 @@ internal static void Restore(object ob, BorrowedReference pyHandle, Dictionary<s

protected override void OnLoad(BorrowedReference ob, Dictionary<string, object?>? context)
{
if (creationBlocked)
throw new InvalidOperationException("Reflected objects should not be loaded anymore.");

base.OnLoad(ob, context);
GCHandle gc = GCHandle.Alloc(this);
SetGCHandle(ob, gc);
Expand Down