diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index c1b663d22..ae380512a 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; @@ -12,11 +13,16 @@ namespace Python.Runtime /// public class PythonEngine : IDisposable { + private const int NUM_GENERATIONS = 3; + private static DelegateManager delegateManager; private static bool initialized; private static IntPtr _pythonHome = IntPtr.Zero; private static IntPtr _programName = IntPtr.Zero; private static IntPtr _pythonPath = IntPtr.Zero; + private static IntPtr _refChain = IntPtr.Zero; + private static IntPtr[] _generations; + public PythonEngine() { @@ -169,6 +175,10 @@ public static void Initialize(IEnumerable args, bool setSysArgv = true, initialized = true; Exceptions.Clear(); + _generations = GetGCGenerations(); +#if PYTHON_WITH_PYDEBUG + _refChain = GetRefChainHead(); +#endif // Make sure we clean up properly on app domain unload. AppDomain.CurrentDomain.DomainUnload += OnDomainUnload; @@ -318,6 +328,9 @@ public static void Shutdown() ExecuteShutdownHandlers(); + Runtime.Shutdown(); + ResetGC(); + initialized = false; } } @@ -598,6 +611,62 @@ internal static PyObject RunString(string code, IntPtr? globals, IntPtr? locals, } } } + + internal static void ResetGC() + { + ClearGC(); +#if PYTHON_WITH_PYDEBUG + ResetRefChain(); +#endif + } + + private static void ClearGC() + { + Debug.Assert(_generations != null); + foreach (IntPtr head in _generations) + { + // gc.gc_next + Marshal.WriteIntPtr(head, 0, head); + // gc.gc_prev + Marshal.WriteIntPtr(head, IntPtr.Size, head); + } + } + + private static IntPtr[] GetGCGenerations() + { + int GCHeadOffset = IntPtr.Size == 4 ? 24 : 32; + IntPtr op = Runtime._PyObject_GC_New(Runtime.PyTypeType); + Runtime.PyObject_GC_Track(op); + IntPtr g = Runtime._Py_AS_GC(op); + // According to _PyObjct_GC_TRACK and PyGC_Head strcture, g is the g->gc.gc_next + // It also become the GEN_HEAD(0) now + IntPtr[] gens = new IntPtr[NUM_GENERATIONS]; + for (int i = 0; i < NUM_GENERATIONS; i++) + { + gens[i] = g; + g += GCHeadOffset; + } + Runtime.PyObject_GC_UnTrack(op); + Runtime.PyObject_GC_Del(op); + return gens; + } + +#if PYTHON_WITH_PYDEBUG + private static void ResetRefChain() + { + Debug.Assert(_refChain != IntPtr.Zero); + Marshal.WriteIntPtr(_refChain, ObjectOffset._ob_next, _refChain); + Marshal.WriteIntPtr(_refChain, ObjectOffset._ob_prev, _refChain); + } + + private static IntPtr GetRefChainHead() + { + IntPtr op = Runtime._PyObject_GC_New(Runtime.PyBaseObjectType); + IntPtr refchain = Marshal.ReadIntPtr(op, ObjectOffset._ob_prev); + Runtime.PyObject_GC_Del(op); + return refchain; + } +#endif } public enum RunFlagType diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 7623200e0..2b62024db 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -1872,7 +1872,7 @@ internal static IntPtr PyType_GenericAlloc(IntPtr type, long n) internal static extern IntPtr _PyObject_GetDictPtr(IntPtr obj); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] - internal static extern IntPtr PyObject_GC_New(IntPtr tp); + internal static extern IntPtr _PyObject_GC_New(IntPtr tp); [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyObject_GC_Del(IntPtr tp); @@ -1907,6 +1907,10 @@ internal static IntPtr PyMem_Realloc(IntPtr ptr, long size) [DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)] internal static extern void PyMem_Free(IntPtr ptr); + internal static IntPtr _Py_AS_GC(IntPtr op) + { + return op - IntPtr.Size; + } //==================================================================== // Python exception API pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy