From f93e9a21676eec0f6fe8018182b256da9fb3b254 Mon Sep 17 00:00:00 2001 From: Victor Nova Date: Tue, 21 Sep 2021 15:21:21 -0700 Subject: [PATCH] remove risky finalization code from Dispatcher, and use reference types --- src/runtime/converter.cs | 2 + src/runtime/delegatemanager.cs | 87 ++++++++++------------------------ src/runtime/importhook.cs | 2 +- src/runtime/runtime.cs | 6 ++- 4 files changed, 33 insertions(+), 64 deletions(-) diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 420fc9435..9dfb6cc45 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -112,6 +112,8 @@ internal static IntPtr ToPython(T value) internal static NewReference ToPythonReference(T value) => NewReference.DangerousFromPointer(ToPython(value, typeof(T))); + internal static NewReference ToPythonReference(object value, Type type) + => NewReference.DangerousFromPointer(ToPython(value, type)); private static readonly Func IsTransparentProxy = GetIsTransparentProxy(); diff --git a/src/runtime/delegatemanager.cs b/src/runtime/delegatemanager.cs index 22f603400..d4fc124fa 100644 --- a/src/runtime/delegatemanager.cs +++ b/src/runtime/delegatemanager.cs @@ -29,21 +29,6 @@ public DelegateManager() dispatch = basetype.GetMethod("Dispatch"); } - /// - /// Given a true delegate instance, return the PyObject handle of the - /// Python object implementing the delegate (or IntPtr.Zero if the - /// delegate is not implemented in Python code. - /// - public IntPtr GetPythonHandle(Delegate d) - { - if (d?.Target is Dispatcher) - { - var disp = (Dispatcher)d.Target; - return disp.target; - } - return IntPtr.Zero; - } - /// /// GetDispatcher is responsible for creating a class that provides /// an appropriate managed callback method for a given delegate type. @@ -224,41 +209,15 @@ A possible alternate strategy would be to create custom subclasses public class Dispatcher { - public IntPtr target; - public Type dtype; - private bool _disposed = false; - private bool _finalized = false; + readonly PyObject target; + readonly Type dtype; public Dispatcher(IntPtr target, Type dtype) { - Runtime.XIncref(target); - this.target = target; + this.target = new PyObject(new BorrowedReference(target)); this.dtype = dtype; } - ~Dispatcher() - { - if (_finalized || _disposed) - { - return; - } - _finalized = true; - Finalizer.Instance.AddFinalizedObject(ref target); - } - - public void Dispose() - { - if (_disposed) - { - return; - } - _disposed = true; - Runtime.XDecref(target); - target = IntPtr.Zero; - dtype = null; - GC.SuppressFinalize(this); - } - public object Dispatch(object[] args) { IntPtr gs = PythonEngine.AcquireLock(); @@ -280,26 +239,36 @@ private object TrueDispatch(object[] args) { MethodInfo method = dtype.GetMethod("Invoke"); ParameterInfo[] pi = method.GetParameters(); - IntPtr pyargs = Runtime.PyTuple_New(pi.Length); Type rtype = method.ReturnType; - for (var i = 0; i < pi.Length; i++) + NewReference op; + using (var pyargs = NewReference.DangerousFromPointer(Runtime.PyTuple_New(pi.Length))) { - // Here we own the reference to the Python value, and we - // give the ownership to the arg tuple. - IntPtr arg = Converter.ToPython(args[i], pi[i].ParameterType); - Runtime.PyTuple_SetItem(pyargs, i, arg); - } + for (var i = 0; i < pi.Length; i++) + { + // Here we own the reference to the Python value, and we + // give the ownership to the arg tuple. + var arg = Converter.ToPythonReference(args[i], pi[i].ParameterType); + if (arg.IsNull()) + { + throw PythonException.ThrowLastAsClrException(); + } + int res = Runtime.PyTuple_SetItem(pyargs, i, arg.Steal()); + if (res != 0) + { + throw PythonException.ThrowLastAsClrException(); + } + } - IntPtr op = Runtime.PyObject_Call(target, pyargs, IntPtr.Zero); - Runtime.XDecref(pyargs); + op = Runtime.PyObject_Call(target.Reference, pyargs, BorrowedReference.Null); + } - if (op == IntPtr.Zero) + if (op.IsNull()) { throw PythonException.ThrowLastAsClrException(); } - try + using (op) { int byRefCount = pi.Count(parameterInfo => parameterInfo.ParameterType.IsByRef); if (byRefCount > 0) @@ -339,7 +308,7 @@ private object TrueDispatch(object[] args) Type t = pi[i].ParameterType; if (t.IsByRef) { - IntPtr item = Runtime.PyTuple_GetItem(op, index++); + BorrowedReference item = Runtime.PyTuple_GetItem(op, index++); if (!Converter.ToManaged(item, t, out object newArg, true)) { Exceptions.RaiseTypeError($"The Python function returned a tuple where element {i} was not {t.GetElementType()} (the out parameter type)"); @@ -352,7 +321,7 @@ private object TrueDispatch(object[] args) { return null; } - IntPtr item0 = Runtime.PyTuple_GetItem(op, 0); + BorrowedReference item0 = Runtime.PyTuple_GetItem(op, 0); if (!Converter.ToManaged(item0, rtype, out object result0, true)) { Exceptions.RaiseTypeError($"The Python function returned a tuple where element 0 was not {rtype} (the return type)"); @@ -397,10 +366,6 @@ private object TrueDispatch(object[] args) return result; } - finally - { - Runtime.XDecref(op); - } } } } diff --git a/src/runtime/importhook.cs b/src/runtime/importhook.cs index 1111adc28..d3592c15d 100644 --- a/src/runtime/importhook.cs +++ b/src/runtime/importhook.cs @@ -120,7 +120,7 @@ static void SetupImportHook() var mod_dict = Runtime.PyModule_GetDict(import_hook_module); // reference not stolen due to overload incref'ing for us. Runtime.PyTuple_SetItem(args, 1, mod_dict); - Runtime.PyObject_Call(exec, args, default); + Runtime.PyObject_Call(exec, args, default).Dispose(); // Set as a sub-module of clr. if(Runtime.PyModule_AddObject(ClrModuleReference, "loader", import_hook_module.DangerousGetAddress()) != 0) { diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 261aacd72..318c7b794 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -1013,6 +1013,8 @@ internal static IntPtr PyObject_Type(IntPtr op) internal static NewReference PyObject_Type(BorrowedReference o) => Delegates.PyObject_Type(o); + internal static string PyObject_GetTypeName(BorrowedReference op) + => PyObject_GetTypeName(op.DangerousGetAddress()); internal static string PyObject_GetTypeName(IntPtr op) { IntPtr pyType = PyObject_TYPE(op); @@ -1097,8 +1099,8 @@ internal static IntPtr PyObject_GetAttr(IntPtr pointer, IntPtr name) internal static IntPtr PyObject_Call(IntPtr pointer, IntPtr args, IntPtr kw) => Delegates.PyObject_Call(pointer, args, kw); - internal static IntPtr PyObject_Call(BorrowedReference pointer, BorrowedReference args, BorrowedReference kw) - => Delegates.PyObject_Call(pointer.DangerousGetAddress(), args.DangerousGetAddress(), kw.DangerousGetAddressOrNull()); + internal static NewReference PyObject_Call(BorrowedReference pointer, BorrowedReference args, BorrowedReference kw) + => NewReference.DangerousFromPointer(Delegates.PyObject_Call(pointer.DangerousGetAddress(), args.DangerousGetAddress(), kw.DangerousGetAddressOrNull())); internal static NewReference PyObject_CallObject(BorrowedReference callable, BorrowedReference args) => Delegates.PyObject_CallObject(callable, args); 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