@@ -127,8 +127,8 @@ internal static Version PyVersion
127
127
/// <summary>
128
128
/// Initialize the runtime...
129
129
/// </summary>
130
- /// <remarks>When calling this method after a soft shutdown or a domain reload,
131
- /// this method acquires and releases the GIL. </remarks>
130
+ /// <remarks>Always call this method from the Main thread. After the
131
+ /// first call to this method, the main thread has acquired the GIL.</remarks>
132
132
internal static void Initialize ( bool initSigs = false , ShutdownMode mode = ShutdownMode . Default , bool fromPython = false )
133
133
{
134
134
if ( _isInitialized )
@@ -407,15 +407,21 @@ internal static void Shutdown(ShutdownMode mode)
407
407
GC . Collect ( ) ;
408
408
try
409
409
{
410
- GC . WaitForFullGCComplete ( ) ;
410
+ GC . WaitForPendingFinalizers ( ) ;
411
411
}
412
412
catch ( NotImplementedException )
413
413
{
414
414
// Some clr runtime didn't implement GC.WaitForFullGCComplete yet.
415
415
}
416
416
PyGILState_Release ( state ) ;
417
- // Then release the GIL for good.
418
- PyEval_SaveThread ( ) ;
417
+ // Then release the GIL for good, if there is somehting to release
418
+ // Use the unchecked version as the checked version calls `abort()`
419
+ // if the current state is NULL.
420
+ if ( _PyThreadState_UncheckedGet ( ) != IntPtr . Zero )
421
+ {
422
+ PyEval_SaveThread ( ) ;
423
+ }
424
+
419
425
}
420
426
else
421
427
{
@@ -846,6 +852,9 @@ internal static unsafe long Refcount(IntPtr op)
846
852
[ DllImport ( _PythonDll , CallingConvention = CallingConvention . Cdecl ) ]
847
853
internal static extern IntPtr PyThreadState_Get( ) ;
848
854
855
+ [ DllImport ( _PythonDll , CallingConvention = CallingConvention . Cdecl ) ]
856
+ internal static extern IntPtr _PyThreadState_UncheckedGet( ) ;
857
+
849
858
[ DllImport ( _PythonDll , CallingConvention = CallingConvention . Cdecl ) ]
850
859
internal static extern IntPtr PyThread_get_key_value( IntPtr key ) ;
851
860
0 commit comments