Skip to content

Commit 56d159f

Browse files
committed
Implement proper shutdown for the extension case
1 parent e7f7c63 commit 56d159f

6 files changed

Lines changed: 31 additions & 21 deletions

File tree

‎pythonnet/__init__.py‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,20 @@ def load():
2727
return
2828

2929
from .find_libpython import find_libpython
30-
from os.path import join, dirname, basename
30+
from os.path import join, dirname
3131

3232
if _RUNTIME is None:
33-
# TODO: Warn, in the future the runtime must be set explicitly, either as a
34-
# config/env variable or via set_runtime
33+
# TODO: Warn, in the future the runtime must be set explicitly, either
34+
# as a config/env variable or via set_runtime
3535
set_default_runtime()
3636

3737
dll_path = join(dirname(__file__), "runtime", "Python.Runtime.dll")
3838
libpython = find_libpython()
3939
# TODO: Add dirname of libpython to (DY)LD_LIBRARY_PATH or PATH
4040

4141
if _FFI is None and sys.platform != "win32":
42-
# Load and leak libpython handle s.t. the .NET runtime doesn't dlcloses it
42+
# Load and leak libpython handle s.t. the .NET runtime doesn't dlcloses
43+
# it
4344
import posix
4445

4546
import cffi
@@ -57,7 +58,6 @@ def load():
5758

5859

5960
def unload():
60-
return
6161
if _LOADER_ASSEMBLY is not None:
6262
func = _LOADER_ASSEMBLY["Python.Runtime.Loader.Shutdown"]
6363
if func(b"") != 0:

‎src/runtime/classbase.cs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ public static IntPtr tp_richcompare(IntPtr ob, IntPtr other, int op)
158158
case Runtime.Py_LE:
159159
case Runtime.Py_GT:
160160
case Runtime.Py_GE:
161-
co1 = GetManagedObject(ob) as CLRObject;
161+
co1 = GetManagedObject(ob) as CLRObject;
162162
co2 = GetManagedObject(other) as CLRObject;
163163
if (co1 == null || co2 == null)
164164
{
@@ -354,6 +354,9 @@ public static IntPtr tp_repr(IntPtr ob)
354354
public static void tp_dealloc(IntPtr ob)
355355
{
356356
ManagedType self = GetManagedObject(ob);
357+
if (self == null)
358+
return;
359+
357360
tp_clear(ob);
358361
Runtime.PyObject_GC_UnTrack(self.pyHandle);
359362
Runtime.PyObject_GC_Del(self.pyHandle);

‎src/runtime/constructorbinding.cs‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,20 +155,25 @@ public static IntPtr tp_repr(IntPtr ob)
155155
public new static void tp_dealloc(IntPtr ob)
156156
{
157157
var self = (ConstructorBinding)GetManagedObject(ob);
158-
Runtime.XDecref(self.repr);
159-
self.Dealloc();
158+
if (self != null) {
159+
Runtime.XDecref(self.repr);
160+
self.Dealloc();
161+
}
160162
}
161163

162164
public static int tp_clear(IntPtr ob)
163165
{
164166
var self = (ConstructorBinding)GetManagedObject(ob);
165-
Runtime.Py_CLEAR(ref self.repr);
167+
if (self != null) Runtime.Py_CLEAR(ref self.repr);
166168
return 0;
167169
}
168170

169171
public static int tp_traverse(IntPtr ob, IntPtr visit, IntPtr arg)
170172
{
171173
var self = (ConstructorBinding)GetManagedObject(ob);
174+
if (self == null)
175+
return 0;
176+
172177
int res = PyVisit(self.pyTypeHndl, visit, arg);
173178
if (res != 0) return res;
174179

‎src/runtime/methodbinding.cs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,14 +241,14 @@ public static IntPtr tp_repr(IntPtr ob)
241241
public new static void tp_dealloc(IntPtr ob)
242242
{
243243
var self = (MethodBinding)GetManagedObject(ob);
244-
self.ClearMembers();
245-
self.Dealloc();
244+
self?.ClearMembers();
245+
self?.Dealloc();
246246
}
247247

248248
public static int tp_clear(IntPtr ob)
249249
{
250250
var self = (MethodBinding)GetManagedObject(ob);
251-
self.ClearMembers();
251+
self?.ClearMembers();
252252
return 0;
253253
}
254254

‎src/runtime/pythonengine.cs‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,9 @@ public static void Initialize()
155155
Initialize(setSysArgv: true);
156156
}
157157

158-
public static void Initialize(bool setSysArgv = true, bool initSigs = false, ShutdownMode mode = ShutdownMode.Default, bool ensureGIL = true)
158+
public static void Initialize(bool setSysArgv = true, bool initSigs = false, ShutdownMode mode = ShutdownMode.Default)
159159
{
160-
Initialize(Enumerable.Empty<string>(), setSysArgv: setSysArgv, initSigs: initSigs, mode, ensureGIL);
160+
Initialize(Enumerable.Empty<string>(), setSysArgv: setSysArgv, initSigs: initSigs, mode);
161161
}
162162

163163
/// <summary>
@@ -170,7 +170,7 @@ public static void Initialize(bool setSysArgv = true, bool initSigs = false, Shu
170170
/// interpreter lock (GIL) to call this method.
171171
/// initSigs can be set to 1 to do default python signal configuration. This will override the way signals are handled by the application.
172172
/// </remarks>
173-
public static void Initialize(IEnumerable<string> args, bool setSysArgv = true, bool initSigs = false, ShutdownMode mode = ShutdownMode.Default, bool ensureGIL = true)
173+
public static void Initialize(IEnumerable<string> args, bool setSysArgv = true, bool initSigs = false, ShutdownMode mode = ShutdownMode.Default)
174174
{
175175
if (initialized)
176176
{
@@ -182,7 +182,7 @@ public static void Initialize(IEnumerable<string> args, bool setSysArgv = true,
182182
// during an initial "import clr", and the world ends shortly thereafter.
183183
// This is probably masking some bad mojo happening somewhere in Runtime.Initialize().
184184
delegateManager = new DelegateManager();
185-
Runtime.Initialize(initSigs, mode, ensureGIL: ensureGIL);
185+
Runtime.Initialize(initSigs, mode);
186186
initialized = true;
187187
Exceptions.Clear();
188188

@@ -266,7 +266,7 @@ public static IntPtr InitExt()
266266
{
267267
try
268268
{
269-
Initialize(setSysArgv: false, ensureGIL: false);
269+
Initialize(setSysArgv: false, mode: ShutdownMode.Extension);
270270

271271
// Trickery - when the import hook is installed into an already
272272
// running Python, the standard import machinery is still in

‎src/runtime/runtime.cs‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ internal static Version PyVersion
100100
/// </summary>
101101
/// <remarks>Always call this method from the Main thread. After the
102102
/// first call to this method, the main thread has acquired the GIL.</remarks>
103-
internal static void Initialize(bool initSigs = false, ShutdownMode mode = ShutdownMode.Default, bool ensureGIL = true)
103+
internal static void Initialize(bool initSigs = false, ShutdownMode mode = ShutdownMode.Default)
104104
{
105105
if (_isInitialized)
106106
{
@@ -133,7 +133,7 @@ internal static void Initialize(bool initSigs = false, ShutdownMode mode = Shutd
133133
// If we're coming back from a domain reload or a soft shutdown,
134134
// we have previously released the thread state. Restore the main
135135
// thread state here.
136-
if (ensureGIL)
136+
if (mode != ShutdownMode.Extension)
137137
{
138138
PyGILState_Ensure();
139139
}
@@ -359,7 +359,7 @@ internal static void Shutdown(ShutdownMode mode)
359359
Finalizer.Shutdown();
360360
InternString.Shutdown();
361361

362-
if (mode != ShutdownMode.Normal)
362+
if (mode != ShutdownMode.Normal && mode != ShutdownMode.Extension)
363363
{
364364
PyGC_Collect();
365365
if (mode == ShutdownMode.Soft)
@@ -390,7 +390,8 @@ internal static void Shutdown(ShutdownMode mode)
390390
else
391391
{
392392
ResetPyMembers();
393-
Py_Finalize();
393+
if (mode != ShutdownMode.Extension)
394+
Py_Finalize();
394395
}
395396
}
396397

@@ -2792,6 +2793,7 @@ public enum ShutdownMode
27922793
Normal,
27932794
Soft,
27942795
Reload,
2796+
Extension,
27952797
}
27962798

27972799

0 commit comments

Comments
 (0)