8000 Merge pull request #28 from QuantConnect/fix-memory-leak-finalizer · saaib/pythonnet@928db02 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit 928db02

Browse files
authored
Merge pull request QuantConnect#28 from QuantConnect/fix-memory-leak-finalizer
Fix memory leak finalizer
2 parents 161d442 + c942194 commit 928db02

File tree

7 files changed

+36
-26
lines changed

7 files changed

+36
-26
lines changed

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 1.0.5.18
2+
current_version = 1.0.5.19
33
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.(?P<release>[a-z]+)(?P<dev>\d+))?
44
serialize =
55
{major}.{minor}.{patch}.{release}{dev}

conda.recipe/meta.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package:
22
name: pythonnet
3-
version: "1.0.5.18"
3+
version: "1.0.5.19"
44

55
build:
66
skip: True # [not win]

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ def run(self):
485485

486486
setup(
487487
name="pythonnet",
488-
version="1.0.5.18",
488+
version="1.0.5.19",
489489
description=".Net and Mono integration for Python",
490490
url='https://pythonnet.github.io/',
491491
license='MIT',

src/SharedAssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@
2525
// Version Information. Keeping it simple. May need to revisit for Nuget
2626
// See: https://codingforsmarties.wordpress.com/2016/01/21/how-to-version-assemblies-destined-for-nuget/
2727
// AssemblyVersion can only be numeric
28-
[assembly: AssemblyVersion("1.0.5.18")]
28+
[assembly: AssemblyVersion("1.0.5.19")]

src/clrmodule/ClrModule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public static void initclr()
5353
{
5454
#if USE_PYTHON_RUNTIME_VERSION
5555
// Has no effect until SNK works. Keep updated anyways.
56-
Version = new Version("1.0.5.18"),
56+
Version = new Version("1.0.5.19"),
5757
#endif
5858
CultureInfo = CultureInfo.InvariantCulture
5959
};

src/runtime/finalizer.cs

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ struct PendingArgs
4141
private ConcurrentQueue<IPyDisposable> _objQueue = new ConcurrentQueue<IPyDisposable>();
4242
private bool _pending = false;
4343
private readonly object _collectingLock = new object();
44-
private IntPtr _pendingArgs;
44+
private IntPtr _pendingArgs = IntPtr.Zero;
4545

4646
#region FINALIZER_CHECK
4747

@@ -128,7 +128,7 @@ internal void AddFinalizedObject(IPyDisposable obj)
128128
_objQueue.Enqueue(obj);
129129
}
130130
GC.ReRegisterForFinalize(obj);
131-
if (_objQueue.Count >= Threshold)
131+
if (!_pending && _objQueue.Count >= Threshold)
132132
{
133133
AddPendingCollect();
134134
}
@@ -164,26 +164,28 @@ internal static void Shutdown()
164164

165165
private void AddPendingCollect()
166166
{
167-
if (_pending)
167+
if(Monitor.TryEnter(_collectingLock))
168168
{
169-
return;
170-
}
171-
lock (_collectingLock)
172-
{
173-
if (_pending)
169+
try
174170
{
175-
return;
171+
if (!_pending)
172+
{
173+
_pending = true;
174+
var args = new PendingArgs { cancelled = false };
175+
_pendingArgs = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PendingArgs)));
176+
Marshal.StructureToPtr(args, _pendingArgs, false);
177+
IntPtr func = Marshal.GetFunctionPointerForDelegate(_collectAction);
178+
if (Runtime.Py_AddPendingCall(func, _pendingArgs) != 0)
179+
{
180+
// Full queue, append next time
181+
FreePendingArgs();
182+
_pending = false;
183+
}
184+
}
176185
}
177-
_pending = true;
178-
var args = new PendingArgs() { cancelled = false };
179-
IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(PendingArgs)));
180-
Marshal.StructureToPtr(args, p, false);
181-
_pendingArgs = p;
182-
IntPtr func = Marshal.GetFunctionPointerForDelegate(_collectAction);
183-
if (Runtime.Py_AddPendingCall(func, p) != 0)
186+
finally
184187
{
185-
// Full queue, append next time
186-
_pending = false;
188+
Monitor.Exit(_collectingLock);
187189
}
188190
}
189191
}
@@ -205,8 +207,8 @@ private static int OnPendingCollect(IntPtr arg)
205207
}
206208
finally
207209
{
210+
Instance.FreePendingArgs();
208211
Instance.ResetPending();
209-
Marshal.FreeHGlobal(arg);
210212
}
211213
return 0;
212214
}
@@ -244,12 +246,20 @@ private void DisposeAll()
244246
}
245247
}
246248

249+
private void FreePendingArgs()
250+
{
251+
if (_pendingArgs != IntPtr.Zero)
252+
{
253+
Marshal.FreeHGlobal(_pendingArgs);
254+
_pendingArgs = IntPtr.Zero;
255+
}
256+
}
257+
247258
private void ResetPending()
248259
{
249260
lock (_collectingLock)
250261
{
251262
_pending = false;
252-
_pendingArgs = IntPtr.Zero;
253263
}
254264
}
255265

src/runtime/resources/clr.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Code in this module gets loaded into the main clr module.
33
"""
44

5-
__version__ = "1.0.5.18"
5+
__version__ = "1.0.5.19"
66

77

88
class clrproperty(object):

0 commit comments

Comments
 (0)
0