public static void Finalize(IPythonDerivedType obj) { FieldInfo fi = obj.GetType().GetField("__pyobj__"); CLRObject self = (CLRObject)fi.GetValue(obj); // delete the python object in an asnyc task as we may not be able to acquire // the GIL immediately and we don't want to block the GC thread. var t = Task.Factory.StartNew(() => { // If python's been terminated then there's nothing to do if (0 == Runtime.Py_IsInitialized()) { return; } IntPtr gs = Runtime.PyGILState_Ensure(); try { // the C# object is being destroyed which must mean there are no more // references to the Python object as well so now we can dealloc the // python object. IntPtr dict = Marshal.ReadIntPtr(self.pyHandle, ObjectOffset.DictOffset(self.pyHandle)); if (dict != IntPtr.Zero) { Runtime.Decref(dict); } Runtime.PyObject_GC_Del(self.pyHandle); self.gcHandle.Free(); } finally { Runtime.PyGILState_Release(gs); } }); }
internal static void Shutdown() { if (Runtime.Py_IsInitialized() == 0) { Instance._objQueue = new ConcurrentQueue <IPyDisposable>(); return; } Instance.DisposeAll(); if (Thread.CurrentThread.ManagedThreadId != Runtime.MainManagedThreadId) { if (Instance._pendingArgs == IntPtr.Zero) { Instance.ResetPending(); return; } // Not in main thread just cancel the pending operation to avoid error in different domain // It will make a memory leak unsafe { PendingArgs *args = (PendingArgs *)Instance._pendingArgs; args->cancelled = true; } Instance.ResetPending(); return; } Instance.CallPendingFinalizers(); }
/// <summary> /// Dispose Method /// </summary> /// <remarks> /// The Dispose method provides a way to explicitly release the /// Python objects represented by a PythonException. /// If object not properly disposed can cause AppDomain unload issue. /// See GH#397 and GH#400. /// </remarks> public void Dispose() { if (!disposed) { if (Runtime.Py_IsInitialized() > 0 && !Runtime.IsFinalizing) { IntPtr gs = PythonEngine.AcquireLock(); if (_pyType != IntPtr.Zero) { Runtime.XDecref(_pyType); _pyType = IntPtr.Zero; } if (_pyValue != IntPtr.Zero) { Runtime.XDecref(_pyValue); _pyValue = IntPtr.Zero; } // XXX Do we ever get TraceBack? // if (_pyTB != IntPtr.Zero) { Runtime.XDecref(_pyTB); _pyTB = IntPtr.Zero; } PythonEngine.ReleaseLock(gs); } GC.SuppressFinalize(this); disposed = true; } }
/// <summary> /// Cleanup resources upon shutdown of the Python runtime. /// </summary> internal static void Shutdown() { if (Runtime.Py_IsInitialized() != 0) { Runtime.XDecref(py_clr_module); Runtime.XDecref(root.pyHandle); Runtime.XDecref(py_import); } }
internal static void Shutdown() { if (Runtime.Py_IsInitialized() == 0) { Instance._objQueue = new ConcurrentQueue <IPyDisposable>(); return; } Instance.Collect(forceDispose: true); }
public static void DomainReloadAndGC() { Assert.IsFalse(PythonEngine.IsInitialized); RunAssemblyAndUnload("test1"); Assert.That(PyRuntime.Py_IsInitialized() != 0, "On soft-shutdown mode, Python runtime should still running"); RunAssemblyAndUnload("test2"); Assert.That(PyRuntime.Py_IsInitialized() != 0, "On soft-shutdown mode, Python runtime should still running"); }
public static void Finalize(IPythonDerivedType obj) { FieldInfo fi = obj.GetType().GetField("__pyobj__"); var self = (CLRObject)fi.GetValue(obj); // If python's been terminated then just free the gchandle. lock (Runtime.IsFinalizingLock) { if (0 == Runtime.Py_IsInitialized() || Runtime.IsFinalizing) { if (self.gcHandle.IsAllocated) { self.gcHandle.Free(); } return; } } // delete the python object in an async task as we may not be able to acquire // the GIL immediately and we don't want to block the GC thread. // FIXME: t isn't used Task t = Task.Factory.StartNew(() => { lock (Runtime.IsFinalizingLock) { // If python's been terminated then just free the gchandle. if (0 == Runtime.Py_IsInitialized() || Runtime.IsFinalizing) { if (self.gcHandle.IsAllocated) { self.gcHandle.Free(); } return; } IntPtr gs = Runtime.PyGILState_Ensure(); try { // the C# object is being destroyed which must mean there are no more // references to the Python object as well so now we can dealloc the // python object. Runtime.PyObject_GC_Del(self.pyHandle); self.gcHandle.Free(); } finally { Runtime.PyGILState_Release(gs); } } }); }
/// <summary> /// Cleanup resources upon shutdown of the Python runtime. /// </summary> internal static void Shutdown() { if (Runtime.Py_IsInitialized() == 0) { return; } TeardownNameSpaceTracking(); clrModule.ResetModuleMembers(); Runtime.Py_CLEAR(ref py_clr_module !); root.Dispose(); root = null !; }
/// <summary> /// Dispose Method /// </summary> /// <remarks> /// The Dispose method provides a way to explicitly release the /// Python object represented by a PyObject instance. It is a good /// idea to call Dispose on PyObjects that wrap resources that are /// limited or need strict lifetime control. Otherwise, references /// to Python objects will not be released until a managed garbage /// collection occurs. /// </remarks> protected virtual void Dispose(bool disposing) { if (!disposed) { if (Runtime.Py_IsInitialized() > 0 && !Runtime.IsFinalizing) { IntPtr gs = PythonEngine.AcquireLock(); Runtime.XDecref(obj); obj = IntPtr.Zero; PythonEngine.ReleaseLock(gs); } disposed = true; } }
/// <summary> /// Dispose Method /// </summary> /// /// <remarks> /// The Dispose method provides a way to explicitly release the /// Python object represented by a PyObject instance. It is a good /// idea to call Dispose on PyObjects that wrap resources that are /// limited or need strict lifetime control. Otherwise, references /// to Python objects will not be released until a managed garbage /// collection occurs. /// </remarks> public void Dispose() { if (!disposed) { if (Runtime.Py_IsInitialized() > 0) { IntPtr gs = PythonEngine.AcquireLock(); Runtime.Decref(obj); obj = IntPtr.Zero; PythonEngine.ReleaseLock(gs); } GC.SuppressFinalize(this); disposed = true; } }
/// <summary> /// Cleanup resources upon shutdown of the Python runtime. /// </summary> internal static void Shutdown() { if (Runtime.Py_IsInitialized() == 0) { return; } TeardownNameSpaceTracking(); Runtime.XDecref(py_clr_module); py_clr_module = IntPtr.Zero; Runtime.XDecref(root.pyHandle); root = null; CLRModule.Reset(); }
/// <summary> /// Cleanup resources upon shutdown of the Python runtime. /// </summary> internal static void Shutdown() { if (Runtime.Py_IsInitialized() != 0) { Runtime.XDecref(py_clr_module); Runtime.XDecref(root.pyHandle); // Re-install the original import function IntPtr dict = Runtime.PyImport_GetModuleDict(); IntPtr mod = Runtime.IsPython3 ? Runtime.PyImport_ImportModule("builtins") : Runtime.PyDict_GetItemString(dict, "__builtin__"); Runtime.PyObject_SetAttrString(mod, "__import__", py_import); Runtime.XDecref(py_import); } }
/// <summary> /// Cleanup resources upon shutdown of the Python runtime. /// </summary> internal static void Shutdown() { if (Runtime.Py_IsInitialized() == 0) { return; } RestoreImport(); Runtime.XDecref(py_clr_module); py_clr_module = IntPtr.Zero; Runtime.XDecref(root.pyHandle); root = null; CLRModule.Reset(); }
/// <summary> /// Cleanup resources upon shutdown of the Python runtime. /// </summary> internal static void Shutdown() { if (Runtime.Py_IsInitialized() != 0) { Type type = typeof(Exceptions); foreach (FieldInfo fi in type.GetFields(BindingFlags.Public | BindingFlags.Static)) { var op = (IntPtr)fi.GetValue(type); if (op != IntPtr.Zero) { Runtime.XDecref(op); } } Runtime.XDecref(exceptions_module); Runtime.PyObject_HasAttrString(warnings_module, "xx"); Runtime.XDecref(warnings_module); } }
static void RunDomainReloadSteps <T1, T2>() where T1 : CrossCaller where T2 : CrossCaller { ValueType arg = null; Type type = typeof(Proxy); { AppDomain domain = CreateDomain("test_domain_reload_1"); try { var theProxy = CreateInstanceInstanceAndUnwrap <Proxy>(domain); theProxy.Call("InitPython", ShutdownMode.Reload); var caller = CreateInstanceInstanceAndUnwrap <T1>(domain); arg = caller.Execute(arg); theProxy.Call("ShutdownPython"); } finally { AppDomain.Unload(domain); } } { AppDomain domain = CreateDomain("test_domain_reload_2"); try { var theProxy = CreateInstanceInstanceAndUnwrap <Proxy>(domain); theProxy.Call("InitPython", ShutdownMode.Reload); var caller = CreateInstanceInstanceAndUnwrap <T2>(domain); caller.Execute(arg); theProxy.Call("ShutdownPythonCompletely"); } finally { AppDomain.Unload(domain); } } if (PythonEngine.DefaultShutdownMode == ShutdownMode.Normal) { Assert.IsTrue(PyRuntime.Py_IsInitialized() == 0); } }
/// <summary> /// Dispose Method /// </summary> /// <remarks> /// The Dispose method provides a way to explicitly release the /// Python object represented by a PyObject instance. It is a good /// idea to call Dispose on PyObjects that wrap resources that are /// limited or need strict lifetime control. Otherwise, references /// to Python objects will not be released until a managed garbage /// collection occurs. /// </remarks> protected virtual void Dispose(bool disposing) { if (this.obj == IntPtr.Zero) { return; } if (Runtime.Py_IsInitialized() == 0) { throw new InvalidOperationException("Python runtime must be initialized"); } if (!Runtime.IsFinalizing) { long refcount = Runtime.Refcount(this.obj); Debug.Assert(refcount > 0, "Object refcount is 0 or less"); if (refcount == 1) { Runtime.PyErr_Fetch(out var errType, out var errVal, out var traceback); try { Runtime.XDecref(this.obj); Runtime.CheckExceptionOccurred(); } finally { // Python requires finalizers to preserve exception: // https://docs.python.org/3/extending/newtypes.html#finalization-and-de-allocation Runtime.PyErr_Restore(errType, errVal, traceback); } } else { Runtime.XDecref(this.obj); } } else { throw new InvalidOperationException("Runtime is already finalizing"); } this.obj = IntPtr.Zero; }
internal void AddFinalizedObject(IDisposable obj) { if (!Enable) { return; } if (Runtime.Py_IsInitialized() == 0) { // XXX: Memory will leak if a PyObject finalized after Python shutdown, // for avoiding that case, user should call GC.Collect manual before shutdown. return; } _objQueue.Enqueue(obj); GC.ReRegisterForFinalize(obj); if (_objQueue.Count >= Threshold) { AddPendingCollect(); } }
public static void DomainReloadAndGC() { Assert.IsFalse(PythonEngine.IsInitialized); RunAssemblyAndUnload("test1"); Assert.That(PyRuntime.Py_IsInitialized() != 0, "On soft-shutdown mode, Python runtime should still running"); RunAssemblyAndUnload("test2"); Assert.That(PyRuntime.Py_IsInitialized() != 0, "On soft-shutdown mode, Python runtime should still running"); if (PythonEngine.DefaultShutdownMode == ShutdownMode.Normal) { // The default mode is a normal mode, // it should shutdown the Python VM avoiding influence other tests. PyRuntime.PyGILState_Ensure(); PyRuntime.Py_Finalize(); } }
/// <summary> /// Cleanup resources upon shutdown of the Python runtime. /// </summary> internal static void Shutdown() { if (Runtime.Py_IsInitialized() != 0) { Runtime.XDecref(py_clr_module); py_clr_module = IntPtr.Zero; Runtime.XDecref(root.pyHandle); root = null; hook.Dispose(); hook = null; Runtime.XDecref(py_import); py_import = IntPtr.Zero; CLRModule.ResetFlags(); } }
static void RunDomainReloadSteps <T1, T2>() where T1 : CrossCaller where T2 : CrossCaller { ValueType arg = null; Type type = typeof(Proxy); { AppDomain domain = CreateDomain("test_domain_reload_1"); try { var theProxy = CreateInstanceInstanceAndUnwrap <Proxy>(domain); theProxy.Call(nameof(PythonRunner.InitPython), PyRuntime.PythonDLL); var caller = CreateInstanceInstanceAndUnwrap <T1>(domain); arg = caller.Execute(arg); theProxy.Call("ShutdownPython"); } finally { AppDomain.Unload(domain); } } { AppDomain domain = CreateDomain("test_domain_reload_2"); try { var theProxy = CreateInstanceInstanceAndUnwrap <Proxy>(domain); theProxy.Call(nameof(PythonRunner.InitPython), PyRuntime.PythonDLL); var caller = CreateInstanceInstanceAndUnwrap <T2>(domain); caller.Execute(arg); theProxy.Call("ShutdownPythonCompletely"); } finally { AppDomain.Unload(domain); } } Assert.IsTrue(PyRuntime.Py_IsInitialized() != 0); }
/// <summary> /// Cleanup resources upon shutdown of the Python runtime. /// </summary> internal static void Shutdown() { if (Runtime.Py_IsInitialized() == 0) { return; } Type type = typeof(Exceptions); foreach (FieldInfo fi in type.GetFields(BindingFlags.Public | BindingFlags.Static)) { var op = (PyObject?)fi.GetValue(type); if (op is null) { continue; } op.Dispose(); fi.SetValue(null, null); } exceptions_module.Dispose(); warnings_module.Dispose(); }
private bool disposedValue = false; // To detect redundant calls private void Dispose(bool disposing) { if (!disposedValue) { if (Runtime.Py_IsInitialized() == 0) { throw new InvalidOperationException("Python runtime must be initialized"); } // this also decrements ref count for _view->obj Runtime.PyBuffer_Release(ref _view); _exporter = null; Shape = null; Strides = null; SubOffsets = null; disposedValue = true; } }
//=================================================================== // Cleanup resources upon shutdown of the Python runtime. //=================================================================== internal static void Shutdown() { #if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) if (0 != Runtime.Py_IsInitialized()) { Runtime.Decref(py_clr_module); Runtime.Decref(root.pyHandle); } ModuleDefOffset.FreeModuleDef(module_def); #else if (0 != Runtime.Py_IsInitialized()) { Runtime.Decref(root.pyHandle); Runtime.Decref(root.pyHandle); } #endif if (0 != Runtime.Py_IsInitialized()) { Runtime.Decref(py_import); } }
/// <summary> /// Cleanup resources upon shutdown of the Python runtime. /// </summary> internal static void Shutdown() { if (Runtime.Py_IsInitialized() == 0) { return; } Type type = typeof(Exceptions); foreach (FieldInfo fi in type.GetFields(BindingFlags.Public | BindingFlags.Static)) { var op = (IntPtr)fi.GetValue(type); if (op == IntPtr.Zero) { continue; } Runtime.XDecref(op); fi.SetValue(null, IntPtr.Zero); } exceptions_module.Dispose(); warnings_module.Dispose(); }
/// <summary> /// Cleanup resources upon shutdown of the Python runtime. /// </summary> internal static void Shutdown() { if (Runtime.Py_IsInitialized() == 0) { return; } RestoreImport(); bool shouldFreeDef = Runtime.Refcount(py_clr_module) == 1; Runtime.XDecref(py_clr_module); py_clr_module = IntPtr.Zero; if (shouldFreeDef) { ReleaseModuleDef(); } Runtime.XDecref(root.pyHandle); root = null; CLRModule.Reset(); }