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

Skip to content

Commit ea059ca

Browse files
authored
Merge pull request pythonnet#2386 from Frawak/fix/1977-access-violation-gc
Fix access violation exception on shutdown
2 parents 9ebfbde + 6cdd6d7 commit ea059ca

File tree

5 files changed

+26
-8
lines changed

5 files changed

+26
-8
lines changed

AUTHORS.md

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
- Dmitriy Se ([@dmitriyse](https://github.com/dmitriyse))
3939
- Félix Bourbonnais ([@BadSingleton](https://github.com/BadSingleton))
4040
- Florian Treurniet ([@ftreurni](https://github.com/ftreurni))
41+
- Frank Witscher ([@Frawak](https://github.com/Frawak))
4142
- He-chien Tsai ([@t3476](https://github.com/t3476))
4243
- Inna Wiesel ([@inna-w](https://github.com/inna-w))
4344
- Ivan Cronyn ([@cronan](https://github.com/cronan))

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
2424
- Fixed RecursionError for reverse operators on C# operable types from python. See #2240
2525
- Fixed crash when .NET event has no `AddMethod`
2626
- Fixed probing for assemblies in `sys.path` failing when a path in `sys.path` has invalid characters. See #2376
27+
- Fixed possible access violation exception on shutdown. See ([#1977][i1977])
2728

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

@@ -971,3 +972,4 @@ This version improves performance on benchmarks significantly compared to 2.3.
971972
[i1481]: https://github.com/pythonnet/pythonnet/issues/1481
972973
[i1672]: https://github.com/pythonnet/pythonnet/pull/1672
973974
[i2311]: https://github.com/pythonnet/pythonnet/issues/2311
975+
[i1977]: https://github.com/pythonnet/pythonnet/issues/1977

src/runtime/Finalizer.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ internal static void Shutdown()
191191
Instance.started = false;
192192
}
193193

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

217217
try
218218
{
219-
while (!_objQueue.IsEmpty)
219+
if (disposeObj) while (!_objQueue.IsEmpty)
220220
{
221221
if (!_objQueue.TryDequeue(out var obj))
222222
continue;
@@ -240,7 +240,7 @@ internal nint DisposeAll()
240240
}
241241
}
242242

243-
while (!_derivedQueue.IsEmpty)
243+
if (disposeDerived) while (!_derivedQueue.IsEmpty)
244244
{
245245
if (!_derivedQueue.TryDequeue(out var derived))
246246
continue;
@@ -258,7 +258,7 @@ internal nint DisposeAll()
258258
collected++;
259259
}
260260

261-
while (!_bufferQueue.IsEmpty)
261+
if (disposeBuffer) while (!_bufferQueue.IsEmpty)
262262
{
263263
if (!_bufferQueue.TryDequeue(out var buffer))
264264
continue;

src/runtime/Runtime.cs

+11-4
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ internal static void Initialize(bool initSigs = false)
158158
ClassManager.Reset();
159159
ClassDerivedObject.Reset();
160160
TypeManager.Initialize();
161+
CLRObject.creationBlocked = false;
161162
_typesInitialized = true;
162163

163164
// Initialize modules that depend on the runtime class.
@@ -278,6 +279,10 @@ internal static void Shutdown()
278279
ClearClrModules();
279280
RemoveClrRootModule();
280281

282+
TryCollectingGarbage(MaxCollectRetriesOnShutdown, forceBreakLoops: true,
283+
obj: true, derived: false, buffer: false);
284+
CLRObject.creationBlocked = true;
285+
281286
NullGCHandles(ExtensionType.loadedExtensions);
282287
ClassManager.RemoveClasses();
283288
TypeManager.RemoveTypes();
@@ -295,8 +300,7 @@ internal static void Shutdown()
295300
PyObjectConversions.Reset();
296301

297302
PyGC_Collect();
298-
bool everythingSeemsCollected = TryCollectingGarbage(MaxCollectRetriesOnShutdown,
299-
forceBreakLoops: true);
303+
bool everythingSeemsCollected = TryCollectingGarbage(MaxCollectRetriesOnShutdown);
300304
Debug.Assert(everythingSeemsCollected);
301305

302306
Finalizer.Shutdown();
@@ -328,7 +332,8 @@ internal static void Shutdown()
328332

329333
const int MaxCollectRetriesOnShutdown = 20;
330334
internal static int _collected;
331-
static bool TryCollectingGarbage(int runs, bool forceBreakLoops)
335+
static bool TryCollectingGarbage(int runs, bool forceBreakLoops,
336+
bool obj = true, bool derived = true, bool buffer = true)
332337
{
333338
if (runs <= 0) throw new ArgumentOutOfRangeException(nameof(runs));
334339

@@ -341,7 +346,9 @@ static bool TryCollectingGarbage(int runs, bool forceBreakLoops)
341346
GC.Collect();
342347
GC.WaitForPendingFinalizers();
343348
pyCollected += PyGC_Collect();
344-
pyCollected += Finalizer.Instance.DisposeAll();
349+
pyCollected += Finalizer.Instance.DisposeAll(disposeObj: obj,
350+
disposeDerived: derived,
351+
disposeBuffer: buffer);
345352
}
346353
if (Volatile.Read(ref _collected) == 0 && pyCollected == 0)
347354
{

src/runtime/Types/ClrObject.cs

+8
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@ internal sealed class CLRObject : ManagedType
1111
{
1212
internal readonly object inst;
1313

14+
internal static bool creationBlocked = false;
15+
1416
// "borrowed" references
1517
internal static readonly HashSet<IntPtr> reflectedObjects = new();
1618
static NewReference Create(object ob, BorrowedReference tp)
1719
{
20+
if (creationBlocked)
21+
throw new InvalidOperationException("Reflected objects should not be created anymore.");
22+
1823
Debug.Assert(tp != null);
1924
var py = Runtime.PyType_GenericAlloc(tp, 0);
2025

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

6267
protected override void OnLoad(BorrowedReference ob, Dictionary<string, object?>? context)
6368
{
69+
if (creationBlocked)
70+
throw new InvalidOperationException("Reflected objects should not be loaded anymore.");
71+
6472
base.OnLoad(ob, context);
6573
GCHandle gc = GCHandle.Alloc(this);
6674
SetGCHandle(ob, gc);

0 commit comments

Comments
 (0)