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

Commit64c4ea6

Browse files
dsymelatkin
authored andcommitted
Fix memory leak: not disposing even subscriptions to invalidation events
partially addressesdotnet#106closesdotnet#477commit5505b71Author: Don Syme <donsyme@fastmail.fm>Date: Sun May 31 16:48:05 2015 +1000 fix tests for invalidation handlerscommit0871018Author: Don Syme <donsyme@fastmail.fm>Date: Sun May 31 16:35:47 2015 +1000 add diagnostic counters to signaturecommite8afa9cAuthor: Don Syme <donsyme@fastmail.fm>Date: Sun May 31 15:07:35 2015 +1000 Fix memory leak: not disposing even subscriptions to invalidation events
1 parent3a07cc0 commit64c4ea6

File tree

4 files changed

+55
-3
lines changed

4 files changed

+55
-3
lines changed

‎src/fsharp/build.fs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3875,7 +3875,9 @@ type TcImports(tcConfigP:TcConfigProvider, initialResolutions:TcAssemblyResoluti
38753875

38763876
// Add the invalidation signal handlers to each provider
38773877
for providerin providersdo
3878-
provider.PUntaint((fun tp-> tp.Invalidate.Add(fun _-> invalidateCcu.Trigger("The provider '"+ fileNameOfRuntimeAssembly+"' reported a change"))), m)
3878+
provider.PUntaint((fun tp->
3879+
lethandler= tp.Invalidate.Subscribe(fun _-> invalidateCcu.Trigger("The provider '"+ fileNameOfRuntimeAssembly+"' reported a change"))
3880+
tcImports.AttachDisposeAction(fun()->try handler.Dispose()with_->())), m)
38793881

38803882
match providerswith
38813883
|[]->

‎vsintegration/src/unittests/Resources.MockTypeProviders/DummyProviderForLanguageServiceTesting/TypeProviderEmit.fs‎

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1429,6 +1429,13 @@ module Local =
14291429
failwith(sprintf"Unknown type '%s' in namespace '%s' (contains%s)" typeName namespaceName typenames)
14301430
}
14311431

1432+
// Used by unit testing to check that invalidation handlers are being disconnected
1433+
moduleGlobalCountersForInvalidation=
1434+
let mutableinvalidationHandlersAdded=0
1435+
let mutableinvalidationHandlersRemoved=0
1436+
letGetInvalidationHandlersAdded()= invalidationHandlersAdded
1437+
letGetInvalidationHandlersRemoved()= invalidationHandlersRemoved
1438+
14321439

14331440
typeTypeProviderForNamespaces(namespacesAndTypes:list<(string* list<ProvidedTypeDefinition>)>)=
14341441
letotherNamespaces= ResizeArray<string* list<ProvidedTypeDefinition>>()
@@ -1440,6 +1447,26 @@ type TypeProviderForNamespaces(namespacesAndTypes : list<(string * list<Provided
14401447
yield Local.makeProvidedNamespace namespaceName types|]
14411448

14421449
letinvalidateE=new Event<EventHandler,EventArgs>()
1450+
letinvalidateP= invalidateE.Publish
1451+
letinvalidatePCounting=
1452+
{new obj()with
1453+
memberx.ToString()="<published event>"
1454+
interface IEvent<EventHandler,EventArgs>
1455+
interface IDelegateEvent<EventHandler>with
1456+
membere.AddHandler(d)=
1457+
GlobalCountersForInvalidation.invalidationHandlersAdded<- GlobalCountersForInvalidation.invalidationHandlersAdded+1
1458+
invalidateP.AddHandler(d)
1459+
membere.RemoveHandler(d)=
1460+
GlobalCountersForInvalidation.invalidationHandlersRemoved<- GlobalCountersForInvalidation.invalidationHandlersRemoved+1
1461+
invalidateP.RemoveHandler(d)
1462+
interface System.IObservable<EventArgs>with
1463+
membere.Subscribe(observer)=
1464+
GlobalCountersForInvalidation.invalidationHandlersAdded<- GlobalCountersForInvalidation.invalidationHandlersAdded+1
1465+
letd= invalidateP.Subscribe(observer)
1466+
{new System.IDisposablewith
1467+
memberx.Dispose()=
1468+
GlobalCountersForInvalidation.invalidationHandlersRemoved<- GlobalCountersForInvalidation.invalidationHandlersRemoved+1
1469+
d.Dispose()}}
14431470

14441471
new(namespaceName:string,types:list<ProvidedTypeDefinition>)=new TypeProviderForNamespaces([(namespaceName,types)])
14451472
new()=new TypeProviderForNamespaces([])
@@ -1450,7 +1477,7 @@ type TypeProviderForNamespaces(namespacesAndTypes : list<(string * list<Provided
14501477
memberx.Dispose()=()
14511478
interface ITypeProviderwith
14521479
[<CLIEvent>]
1453-
overridethis.Invalidate=invalidateE.Publish
1480+
overridethis.Invalidate=invalidatePCounting
14541481
overridethis.GetNamespaces()= Array.copy providedNamespaces.Value
14551482
member__.GetInvokerExpression(methodBase,parameters)=
14561483
match methodBasewith

‎vsintegration/src/unittests/Resources.MockTypeProviders/DummyProviderForLanguageServiceTesting/TypeProviderEmit.fsi‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,4 +280,10 @@ type TypeProviderForNamespaces =
280280
member Invalidate: unit-> unit
281281

282282
interface ITypeProvider
283+
284+
// Used by unit testing to check that invalidation handlers are being disconnected
285+
module GlobalCountersForInvalidation=
286+
valGetInvalidationHandlersAdded:unit->int
287+
valGetInvalidationHandlersRemoved:unit->int
288+
283289
#endif

‎vsintegration/src/unittests/Tests.LanguageService.Script.fs‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1629,16 +1629,30 @@ type ScriptTests() as this =
16291629
lettotalDisposalsMeth= providerCounters.GetMethod("GetTotalDisposals")
16301630
Assert.IsNotNull(totalDisposalsMeth,"totalDisposalsMeth should not be null")
16311631

1632+
letproviderCounters2= providerAssembly.GetType("Microsoft.FSharp.TypeProvider.Emit.GlobalCountersForInvalidation")
1633+
Assert.IsNotNull(providerCounters2,"provider counters #2 module should not be null")
1634+
lettotalInvaldiationHandlersAddedMeth= providerCounters2.GetMethod("GetInvalidationHandlersAdded")
1635+
Assert.IsNotNull(totalInvaldiationHandlersAddedMeth,"totalInvaldiationHandlersAddedMeth should not be null")
1636+
lettotalInvaldiationHandlersRemovedMeth= providerCounters2.GetMethod("GetInvalidationHandlersRemoved")
1637+
Assert.IsNotNull(totalInvaldiationHandlersRemovedMeth,"totalInvaldiationHandlersRemovedMeth should not be null")
1638+
16321639
lettotalCreations()= totalCreationsMeth.Invoke(null,[||]):?> int
16331640
lettotalDisposals()= totalDisposalsMeth.Invoke(null,[||]):?> int
1641+
lettotalInvaldiationHandlersAdded()= totalInvaldiationHandlersAddedMeth.Invoke(null,[||]):?> int
1642+
lettotalInvaldiationHandlersRemoved()= totalInvaldiationHandlersRemovedMeth.Invoke(null,[||]):?> int
16341643

16351644

16361645
letstartCreations= totalCreations()
16371646
letstartDisposals= totalDisposals()
1647+
letstartInvaldiationHandlersAdded= totalInvaldiationHandlersAdded()
1648+
letstartInvaldiationHandlersRemoved= totalInvaldiationHandlersRemoved()
16381649
letcountCreations()= totalCreations()- startCreations
16391650
letcountDisposals()= totalDisposals()- startDisposals
1651+
letcountInvaldiationHandlersAdded()= totalInvaldiationHandlersAdded()- startInvaldiationHandlersAdded
1652+
letcountInvaldiationHandlersRemoved()= totalInvaldiationHandlersRemoved()- startInvaldiationHandlersRemoved
16401653

16411654
Assert.IsTrue(startCreations>= startDisposals,"Check0")
1655+
Assert.IsTrue(startInvaldiationHandlersAdded>= startInvaldiationHandlersRemoved,"Check0")
16421656
for iin1..50do
16431657
letsolution= this.CreateSolution()
16441658
letproject= CreateProject(solution,"testproject"+ string(i%20))
@@ -1667,15 +1681,18 @@ type ScriptTests() as this =
16671681
// there should be some roots to project builds still present
16681682
if i>=3then
16691683
Assert.IsTrue(i>= countDisposals()+3,"Check4a, i >= countDisposals() + 3, iteration"+ string i+", i ="+ string i+", countDisposals() ="+ string(countDisposals()))
1684+
printfn"Check4a2, i =%d, countInvaldiationHandlersRemoved() =%d" i(countInvaldiationHandlersRemoved())
16701685

16711686
// If we forcefully clear out caches and force a collection, then we can say much stronger things...
16721687
if clearingthen
16731688
ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients(this.VS)
16741689
Assert.IsTrue((i= countDisposals()),"Check4b, countCreations() = countDisposals(), iteration"+ string i)
1690+
Assert.IsTrue(countInvaldiationHandlersAdded()- countInvaldiationHandlersRemoved()=0,"Check4b2, all invlidation handlers removed, iteration"+ string i)
16751691

16761692
Assert.IsTrue(countCreations()=50,"Check5, at end, countCreations() = 50")
16771693
ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients(this.VS)
1678-
Assert.IsTrue(countDisposals()=50,"Check6b, at end, countDisposals() = 50 when clearing")
1694+
Assert.IsTrue(countDisposals()=50,"Check6b, at end, countDisposals() = 50 after explicit clearing")
1695+
Assert.IsTrue(countInvaldiationHandlersAdded()- countInvaldiationHandlersRemoved()=0,"Check6b2, at end, all invalidation handlers removed after explicit cleraring")
16791696

16801697
[<Test>]
16811698
[<Category("TypeProvider")>]

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp