Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit93594b2

Browse files
committed
Add a test for the memory leak in Async.AwaitHandle - relates todotnet#131
1 parent742c133 commit93594b2

File tree

1 file changed

+43
-0
lines changed
  • src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Control

1 file changed

+43
-0
lines changed

‎src/fsharp/FSharp.Core.Unittests/FSharp.Core/Microsoft.FSharp.Control/AsyncModule.fs‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ open System
99
openFSharp.Core.Unittests.LibraryTestFx
1010
openNUnit.Framework
1111

12+
moduleLeakUtils=
13+
// when testing for liveness, the things that we want to observe must always be created in
14+
// a nested function call to avoid the GC (possibly) treating them as roots past the last use in the block.
15+
// We also need something non trivial to disuade the compiler from inlining in Release builds.
16+
typeToRun<'a>(f: unit->'a)=
17+
memberthis.Invoke()= f()
18+
19+
letrun(toRun:ToRun<'a>)= toRun.Invoke()
1220

1321
// ---------------------------------------------------
1422

@@ -191,6 +199,41 @@ type AsyncModule() =
191199

192200
for_i=1to50do test()
193201

202+
203+
[<Test>]
204+
memberthis.``Async.AwaitWaitHandle does not leak memory``()=
205+
// This test checks that AwaitWaitHandle does not leak continuations (described in #131),
206+
// We only test the worst case - when the AwaitWaitHandle is already set.
207+
use manualResetEvent=new System.Threading.ManualResetEvent(true)
208+
209+
lettryToLeak()=
210+
letresource=
211+
LeakUtils.ToRun(fun()->
212+
letresource= obj()
213+
letwork=
214+
async{
215+
let!_= Async.AwaitWaitHandle manualResetEvent
216+
GC.KeepAlive(resource)
217+
return()
218+
}
219+
220+
work|> Async.RunSynchronously|> ignore
221+
WeakReference(resource))
222+
|> LeakUtils.run
223+
224+
Assert.IsTrue(resource.IsAlive)
225+
226+
GC.Collect()
227+
GC.WaitForPendingFinalizers()
228+
GC.Collect()
229+
GC.WaitForPendingFinalizers()
230+
GC.Collect()
231+
232+
Assert.IsFalse(resource.IsAlive)
233+
234+
// The leak hangs on a race condition which is really hard to trigger in F# 3.0, hence the 100000 runs...
235+
for_in1..100000do tryToLeak()
236+
194237
[<Test>]
195238
memberthis.``AwaitWaitHandle.DisposedWaitHandle2``()=
196239
letwh=new System.Threading.ManualResetEvent(false)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp