8000 * Fix refcnt error · pythonnet/pythonnet@657452e · GitHub
[go: up one dir, main page]

Skip to content

Commit 657452e

Browse files
committed
* Fix refcnt error
* Keep delegate of Thunk in tp_dict * Remove useless code
1 parent 4e19a4f commit 657452e

File tree

10 files changed

+221
-179
lines changed

10 files changed

+221
-179
lines changed

src/runtime/Python.Runtime.csproj

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
33
<PropertyGroup>
44
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -34,7 +34,7 @@
3434
<DebugType>pdbonly</DebugType>
3535
</PropertyGroup>
3636
<PropertyGroup Condition=" '$(Configuration)' == 'ReleaseMonoPY3'">
37-
<DefineConstants Condition="'$(DefineConstants)' == ''">PYTHON3;PYTHON37;UCS4</DefineConstants>
37+
<DefineConstants Condition="'$(DefineConstants)' == ''">PYTHON3;PYTHON37;UCS4</DefineConstants>
3838
<Optimize>true</Optimize>
3939
<DebugType>pdbonly</DebugType>
4040
</PropertyGroup>
@@ -46,7 +46,7 @@
4646
</PropertyGroup>
4747
<PropertyGroup Condition=" '$(Configuration)' == 'DebugMonoPY3'">
4848
<DebugSymbols>true</DebugSymbols>
49-
<DefineConstants Condition="'$(DefineConstants)' == ''">PYTHON3;PYTHON37;UCS4;TRACE;DEBUG</DefineConstants>
49+
<DefineConstants Condition="'$(DefineConstants)' == ''">PYTHON3;PYTHON37;UCS4;TRACE;DEBUG</DefineConstants>
5050
<Optimize>false</Optimize>
5151
<DebugType>full</DebugType>
5252
</PropertyGroup>
@@ -56,7 +56,7 @@
5656
<DebugType>pdbonly</DebugType>
5757
</PropertyGroup>
5858
<PropertyGroup Condition=" '$(Configuration)' == 'ReleaseWinPY3'">
59-
<DefineConstants Condition="'$(DefineConstants)' == ''">PYTHON3;PYTHON37;UCS2</DefineConstants>
59+
<DefineConstants Condition="'$(DefineConstants)' == ''">PYTHON3;PYTHON37;UCS2</DefineConstants>
6060
<Optimize>true</Optimize>
6161
<DebugType>pdbonly</DebugType>
6262
</PropertyGroup>
@@ -68,7 +68,7 @@
6868
</PropertyGroup>
6969
<PropertyGroup Condition=" '$(Configuration)' == 'DebugWinPY3'">
7070
<DebugSymbols>true</DebugSymbols>
71-
<DefineConstants Condition="'$(DefineConstants)' == ''">PYTHON3;PYTHON37;UCS2;TRACE;DEBUG</DefineConstants>
71+
<DefineConstants Condition="'$(DefineConstants)' == ''">PYTHON3;PYTHON37;UCS2;TRACE;DEBUG</DefineConstants>
7272
<Optimize>false</Optimize>
7373
<DebugType>full</DebugType>
7474
</PropertyGroup>
@@ -137,11 +137,12 @@
137137
<Compile Include="pythonexception.cs" />
138138
<Compile Include="pytuple.cs" />
139139
<Compile Include="runtime.cs" />
140+
<Compile Include="runtime_state.cs" />
140141
<Compile Include="typemanager.cs" />
141142
<Compile Include="typemethod.cs" />
142143
<Compile Include="Util.cs" />
143-
<Compile Include="platform\Types.cs" />
144-
<Compile Include="platform\LibraryLoader.cs" />
144+
<Compile Include="platform\Types.cs" />
145+
<Compile Include="platform\LibraryLoader.cs" />
145146
</ItemGroup>
146147
<ItemGroup Condition=" '$(PythonInteropFile)' != '' ">
147148
<Compile Include="$(PythonInteropFile)" />
@@ -151,7 +152,7 @@
151152
<Compile Include="interop34.cs" />
152153
<Compile Include="interop35.cs" />
153154
<Compile Include="interop36.cs" />
154-
<Compile Include="interop37.cs" />
155+
<Compile Include="interop37.cs" />
155156
</ItemGroup>
156157
<ItemGroup>
157158
<None Include="..\pythonnet.snk" />
@@ -170,4 +171,4 @@
170171
<Copy SourceFiles="$(TargetAssembly)" DestinationFolder="$(PythonBuildDir)" />
171172
<!--Copy SourceFiles="$(TargetAssemblyPdb)" Condition="Exists('$(TargetAssemblyPdb)')" DestinationFolder="$(PythonBuildDir)" /-->
172173
</Target>
173-
</Project>
174+
</Project>

src/runtime/classmanager.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ internal static void RemoveClasses()
5656
cls.TypeTraverse(OnVisit, visitedPtr);
5757
// XXX: Force release some resouces.
5858
cls.TypeClear();
59-
//Runtime.XDecref(cls.pyHandle);
6059
}
6160
}
6261
finally
@@ -189,8 +188,7 @@ private static void InitClassBase(Type type, ClassBase impl)
189188
var name = (string)iter.Key;
190189
Runtime.PyDict_SetItemString(dict, name, item.pyHandle);
191190
// info.members are already useless
192-
Runtime.XDecref(item.pyHandle);
193-
item.pyHandle = IntPtr.Zero;
191+
item.DecrRefCount();
194192
}
195193

196194
// If class has constructors, generate an __doc__ attribute.
@@ -225,6 +223,7 @@ private static void InitClassBase(Type type, ClassBase impl)
225223
// TODO: deprecate __overloads__ soon...
226224
Runtime.PyDict_SetItemString(dict, "__overloads__", ctors.pyHandle);
227225
Runtime.PyDict_SetItemString(dict, "Overloads", ctors.pyHandle);
226+
ctors.DecrRefCount();
228227
}
229228

230229
// don't generate the docstring if one was already set from a DocStringAttribute.

src/runtime/extensiontype.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public ExtensionType()
3838

3939
Runtime.PyObject_GC_UnTrack(py);
4040

41+
// Steals a ref to tpHandle.
4142
tpHandle = tp;
4243
pyHandle = py;
4344
}
@@ -49,7 +50,8 @@ public ExtensionType()
4950
public static void FinalizeObject(ManagedType self)
5051
{
5152
Runtime.PyObject_GC_Del(self.pyHandle);
52-
Runtime.XDecref(self.tpHandle);
53+
// Not necessary decref for `tpHandle`.
54+
// Runtime.XDecref(self.tpHandle);
5355
self.FreeGCHandle();
5456
}
5557

src/runtime/importhook.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ internal static void Initialize()
4343
py_import = Runtime.PyObject_GetAttrString(mod, "__import__");
4444
hook = new MethodWrapper(typeof(ImportHook), "__import__", "TernaryFunc");
4545
Runtime.PyObject_SetAttrString(mod, "__import__", hook.ptr);
46-
Runtime.XDecref(hook.ptr);
4746

4847
root = new CLRModule();
4948

@@ -88,7 +87,7 @@ internal static void Shutdown()
8887
Runtime.XDecref(root.pyHandle);
8988
root = null;
9089

91-
hook.Dispose();
90+
hook.Release();
9291
hook = null;
9392

9493
Runtime.XDecref(py_import);

src/runtime/interop.cs

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,6 @@ internal class TypeFlags
335335

336336
internal class Interop
337337
{
338-
private static Dictionary<KeyValuePair<MethodInfo,string>, Tuple<Delegate, IntPtr>> keepAlive;
339338
private static Hashtable pmap;
340339

341340
static Interop()
@@ -352,8 +351,6 @@ static Interop()
352351
p[item.Name] = item;
353352
}
354353

355-
keepAlive = new Dictionary<KeyValuePair<MethodInfo, string>, Tuple<Delegate, IntPtr>>();
356-
//Marshal.AllocHGlobal(IntPtr.Size);
357354
pmap = new Hashtable();
358355

359356
pmap["tp_dealloc"] = p["DestructorFunc"];
@@ -450,24 +447,12 @@ internal static Type GetPrototype(string name)
450447
return pmap[name] as Type;
451448
}
452449

453-
internal static IntPtr GetThunk(MethodInfo method, string funcType = null)
450+
internal static ThunkInfo GetThunk(MethodInfo method, string funcType = null)
454451
{
455-
var key = new KeyValuePair<MethodInfo, string>(method, funcType);
456-
Tuple<Delegate, IntPtr> thunkPair;
457-
if (keepAlive.TryGetValue(key, out thunkPair))
458-
{
459-
return thunkPair.Item2;
460-
}
461-
thunkPair = GetThunkImpl(method, funcType);
462-
if (thunkPair == null)
463-
{
464-
return IntPtr.Zero;
465-
}
466-
keepAlive[key] = thunkPair;
467-
return thunkPair.Item2;
452+
return GetThunkImpl(method, funcType);
468453
}
469454

470-
private static Tuple<Delegate, IntPtr> GetThunkImpl(MethodInfo method, string funcType)
455+
private static ThunkInfo GetThunkImpl(MethodInfo method, string funcType)
471456
{
472457
Type dt;
473458
if (funcType != null)
@@ -477,15 +462,15 @@ private static Tuple<Delegate, IntPtr> GetThunkImpl(MethodInfo method, string fu
477462

478463
if (dt == null)
479464
{
480-
return null;
465+
return ThunkInfo.Empty;
481466
}
482467
IntPtr tmp = Marshal.AllocHGlobal(IntPtr.Size);
483468
Delegate d = Delegate.CreateDelegate(dt, method);
484469
Thunk cb = new Thunk(d);
485470
Marshal.StructureToPtr(cb, tmp, false);
486471
IntPtr fp = Marshal.ReadIntPtr(tmp, 0);
487472
Marshal.FreeHGlobal(tmp);
488-
return new Tuple<Delegate, IntPtr>(d, fp);
473+
return new ThunkInfo(d, fp);
489474
}
490475

491476
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
@@ -540,6 +525,19 @@ public Thunk(Delegate d)
540525
}
541526
}
542527

528+
internal struct ThunkInfo
529+
{
530+
public Delegate Target;
531+
public IntPtr Address;
532+
533+
public static readonly ThunkInfo Empty = new ThunkInfo(null, IntPtr.Zero);
534+
535+
public ThunkInfo(Delegate target, IntPtr addr)
536+
{
537+
Target = target;
538+
Address = addr;
539+
}
540+
}
543541

544542
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
545543
struct PyGC_Node

src/runtime/methodwrapper.cs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,51 +8,46 @@ namespace Python.Runtime
88
/// currently used mainly to implement special cases like the CLR
99
/// import hook.
1010
/// </summary>
11-
internal class MethodWrapper : IDisposable
11+
internal class MethodWrapper
1212
{
1313
public IntPtr mdef;
1414
public IntPtr ptr;
15+
public ThunkInfo _thunk;
1516
private bool _disposed = false;
1617

1718
public MethodWrapper(Type type, string name, string funcType = null)
1819
{
1920
// Turn the managed method into a function pointer
2021

21-
IntPtr fp = Interop.GetThunk(type.GetMethod(name), funcType);
22+
_thunk = Interop.GetThunk(type.GetMethod(name), funcType);
2223

2324
// Allocate and initialize a PyMethodDef structure to represent
2425
// the managed method, then create a PyCFunction.
2526

2627
mdef = Runtime.PyMem_Malloc(4 * IntPtr.Size);
27-
TypeManager.WriteMethodDef(mdef, name, fp, 0x0003);
28+
TypeManager.WriteMethodDef(mdef, name, _thunk.Address, 0x0003);
2829
ptr = Runtime.PyCFunction_NewEx(mdef, IntPtr.Zero, IntPtr.Zero);
2930
}
3031

31-
~MethodWrapper()
32-
{
33-
Dispose();
34-
}
3532

3633
public IntPtr Call(IntPtr args, IntPtr kw)
3734
{
3835
return Runtime.PyCFunction_Call(ptr, args, kw);
3936
}
4037

41-
public void Dispose()
38+
public void Release()
4239
{
4340
if (_disposed)
4441
{
4542
return;
4643
}
47-
using (Py.GIL())
44+
_disposed = true;
45+
bool freeDef = Runtime.Refcount(ptr) == 1;
46+
Runtime.XDecref(ptr);
47+
if (freeDef && mdef != IntPtr.Zero)
4848
{
49-
_disposed = true;
50-
Runtime.XDecref(ptr);
51-
if (mdef != IntPtr.Zero)
52-
{
53-
Runtime.PyMem_Free(mdef);
54-
mdef = IntPtr.Zero;
55-
}
49+
Runtime.PyMem_Free(mdef);
50+
mdef = IntPtr.Zero;
5651
}
5752
}
5853
}

src/runtime/pythonengine.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,7 @@ public static void Initialize(IEnumerable<string> args, bool setSysArgv = true,
213213
Runtime.PyDict_SetItemString(module_globals, "__builtins__", builtins);
214214

215215
Assembly assembly = Assembly.GetExecutingAssembly();
216-
Stream stream = assembly.GetManifestResourceStream("clr.py");
217-
if (stream == null)
218-
{
219-
stream = File.OpenRead(@"I:\repos\pythonnet\src\runtime\resources\clr.py");
220-
}
221-
using (stream)
216+
using (Stream stream = assembly.GetManifestResourceStream("clr.py"))
222217
using (var reader = new StreamReader(stream))
223218
{
224219
// add the contents of clr.py to the module

0 commit comments

Comments
 (0)
0