8000 dispose registered codecs and interop configuration during shutdown · pythonnet/pythonnet@62e2fb4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 62e2fb4

Browse files
committed
dispose registered codecs and interop configuration during shutdown
1 parent 4f657d4 commit 62e2fb4

File tree

10 files changed

+64
-8
lines changed

10 files changed

+64
-8
lines changed

src/embed_tests/Codecs.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,13 +421,18 @@ public PyObject TryEncode(object value)
421421
}
422422
}
423423

424-
class InstancelessExceptionDecoder : IPyObjectDecoder
424+
class InstancelessExceptionDecoder : IPyObjectDecoder, IDisposable
425425
{
426426
readonly PyObject PyErr = Py.Import("clr.interop").GetAttr("PyErr");
427427

428428
public bool CanDecode(PyType objectType, Type targetType)
429429
=> PythonReferenceComparer.Instance.Equals(PyErr, objectType);
430430

431+
public void Dispose()
432+
{
433+
PyErr.Dispose();
434+
}
435+
431436
public bool TryDecode<T>(PyObject pyObj, out T value)
432437 {
433438
if (pyObj.HasAttr("value"))

src/embed_tests/Inheritance.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public void SetUp()
2424
[OneTimeTearDown]
2525
public void Dispose()
2626
{
27+
ExtraBaseTypeProvider.ExtraBase.Dispose();
2728
PythonEngine.Shutdown();
2829
}
2930

src/embed_tests/pyinitialize.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ public static void TestRunExitFuncs()
176176
{
177177
Assert.Fail(msg);
178178
}
179+
PythonEngine.InteropConfiguration = InteropConfiguration.MakeDefault();
179180
return;
180181
}
181182
bool called = false;
@@ -187,6 +188,7 @@ public static void TestRunExitFuncs()
187188
atexit.Dispose();
188189
Runtime.Runtime.Shutdown();
189190
Assert.True(called);
191+
PythonEngine.InteropConfiguration = InteropConfiguration.MakeDefault();
190192
}
191193
}
192194

src/runtime/Codecs/DecoderGroup.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Python.Runtime.Codecs
88
/// <summary>
99
/// Represents a group of <see cref="IPyObjectDecoder"/>s. Useful to group them by priority.
1010
/// </summary>
11-
public sealed class DecoderGroup: IPyObjectDecoder, IEnumerable<IPyObjectDecoder>
11+
public sealed class DecoderGroup: IPyObjectDecoder, IEnumerable<IPyObjectDecoder>, IDisposable
1212
{
1313
readonly List<IPyObjectDecoder> decoders = new List<IPyObjectDecoder>();
1414

@@ -46,6 +46,15 @@ public bool TryDecode<T>(PyObject pyObj, out T value)
4646
/// <inheritdoc />
4747
public IEnumerator<IPyObjectDecoder> GetEnumerator() => this.decoders.GetEnumerator();
4848
IEnumerator IEnumerable.GetEnumerator() => this.decoders.GetEnumerator();
49+
50+
public void Dispose()
51+
{
52+
foreach (var decoder in this.decoders.OfType<IDisposable>())
53+
{
54+
decoder.Dispose();
55+
}
56+
this.decoders.Clear();
57+
}
4958
}
5059

5160
public static class DecoderGroupExtensions

src/runtime/Codecs/EncoderGroup.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Python.Runtime.Codecs
88
/// <summary>
99
/// Represents a group of <see cref="IPyObjectDecoder"/>s. Useful to group them by priority.
1010
/// </summary>
11-
public sealed class EncoderGroup: IPyObjectEncoder, IEnumerable<IPyObjectEncoder>
11+
public sealed class EncoderGroup: IPyObjectEncoder, IEnumerable<IPyObjectEncoder>, IDisposable
1212
{
1313
readonly List<IPyObjectEncoder> encoders = new List<IPyObjectEncoder>();
1414

@@ -47,6 +47,15 @@ public PyObject TryEncode(object value)
4747
/// <inheritdoc />
4848
public IEnumerator<IPyObjectEncoder> GetEnumerator() => this.encoders.GetEnumerator();
4949
IEnumerator IEnumerable.GetEnumerator() => this.encoders.GetEnumerator();
50+
51+
public void Dispose()
52+
{
53+
foreach (var encoder in this.encoders.OfType<IDisposable>())
54+
{
55+
encoder.Dispose();
56+
}
57+
this.encoders.Clear();
58+
}
5059
}
5160

5261
public static class EncoderGroupExtensions

src/runtime/InteropConfiguration.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ namespace Python.Runtime
22
{
33
using System;
44
using System.Collections.Generic;
5+
using System.Linq;
56

67
using Python.Runtime.Mixins;
78

8-
public sealed class InteropConfiguration
9+
public sealed class InteropConfiguration: IDisposable
910
{
1011
internal readonly PythonBaseTypeProviderGroup pythonBaseTypeProviders
1112
= new PythonBaseTypeProviderGroup();
@@ -24,5 +25,14 @@ public static InteropConfiguration MakeDefault()
2425
},
2526
};
2627
}
28+
29+
public void Dispose()
30+
{
31+
foreach (var provider in PythonBaseTypeProviders.OfType<IDisposable>())
32+
{
33+
provider.Dispose();
34+
}
35+
PythonBaseTypeProviders.Clear();
36+
}
2737
}
2838
}

src/runtime/Mixins/CollectionMixinsProvider.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
namespace Python.Runtime.Mixins
66
{
7-
class CollectionMixinsProvider : IPythonBaseTypeProvider
7+
class CollectionMixinsProvider : IPythonBaseTypeProvider, IDisposable
88
{
99
readonly Lazy<PyObject> mixinsModule;
1010
public CollectionMixinsProvider(Lazy<PyObject> mixinsModule)
@@ -86,5 +86,13 @@ static Type[] NewInterfaces(Type type)
8686

8787
static Type GetDefinition(Type type)
8888
=> type.IsGenericType ? type.GetGenericTypeDefinition() : type;
89+
90+
public void Dispose()
91+
{
92+
if (this.mixinsModule.IsValueCreated)
93+
{
94+
this.mixinsModule.Value.Dispose();
95+
}
96+
}
8997
}
9098
}

src/runtime/converterextensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,8 @@ internal static void Reset()
166166
{
167167
clrToPython.Clear();
168168
pythonToClr.Clear();
169-
encoders.Clear();
170-
decoders.Clear();
169+
encoders.Dispose();
170+
decoders.Dispose();
171171
}
172172
}
173173

src/runtime/pythonengine.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,6 @@ public static void Shutdown(ShutdownMode mode)
381381
ExecuteShutdownHandlers();
382382
// Remember to shut down the runtime.
383383
Runtime.Shutdown(mode);
384-
PyObjectConversions.Reset();
385384

386385
initialized = false;
387386

src/runtime/runtime.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,11 @@ internal static void Shutdown(ShutdownMode mode)
373373
PyCLRMetaType = IntPtr.Zero;
374374

375375
Exceptions.Shutdown();
376+
PythonEngine.InteropConfiguration.Dispose();
377+
DisposeLazyModule(clrInterop);
378+
DisposeLazyModule(inspect);
379+
PyObjectConversions.Reset();
380+
376381
Finalizer.Shutdown();
377382
InternString.Shutdown();
378383

@@ -424,6 +429,14 @@ internal static void Shutdown()
424429
Shutdown(mode);
425430
}
426431

432+
static void DisposeLazyModule(Lazy<PyObject> module)
433+
{
434+
if (module.IsValueCreated)
435+
{
436+
module.Value.Dispose();
437+
}
438+
}
439+
427440
private static Lazy<PyObject> GetModuleLazy(string moduleName)
428441
=> moduleName is null
429442
? throw new ArgumentNullException(nameof(moduleName))

0 commit comments

Comments
 (0)
0