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

Commite8afa9c

Browse files
committed
Fix memory leak: not disposing even subscriptions to invalidation events
1 parent3a07cc0 commite8afa9c

File tree

3 files changed

+51
-3
lines changed

3 files changed

+51
-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/Tests.LanguageService.Script.fs‎

Lines changed: 20 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))
@@ -1662,20 +1676,25 @@ type ScriptTests() as this =
16621676
Assert.IsTrue(countDisposals()< i,"Check1, countDisposals() < i, iteration"+ string i)
16631677
Assert.IsTrue(countCreations()>= countDisposals(),"Check2, countCreations() >= countDisposals(), iteration"+ string i)
16641678
Assert.IsTrue(countCreations()= i,"Check3, countCreations() = i, iteration"+ string i)
1679+
Assert.IsTrue(countInvaldiationHandlersAdded()= i,"Check3b, countInvaldiationHandlersAdded() = i, iteration"+ string i)
16651680
ifnot clearingthen
16661681
// By default we hold 3 build incrementalBuilderCache entries and 5 typeCheckInfo entries, so if we're not clearing
16671682
// there should be some roots to project builds still present
16681683
if i>=3then
16691684
Assert.IsTrue(i>= countDisposals()+3,"Check4a, i >= countDisposals() + 3, iteration"+ string i+", i ="+ string i+", countDisposals() ="+ string(countDisposals()))
1685+
Assert.IsTrue(i>= countInvaldiationHandlersRemoved()+3,"Check4a2, i >= countInvaldiationHandlersRemoved() + 3, iteration"+ string i+", i ="+ string i+", countDisposals() ="+ string(countDisposals()))
16701686

16711687
// If we forcefully clear out caches and force a collection, then we can say much stronger things...
16721688
if clearingthen
16731689
ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients(this.VS)
16741690
Assert.IsTrue((i= countDisposals()),"Check4b, countCreations() = countDisposals(), iteration"+ string i)
1691+
Assert.IsTrue((i= countInvaldiationHandlersRemoved()),"Check4b2, countCreations() = countInvaldiationHandlersRemoved(), iteration"+ string i)
16751692

16761693
Assert.IsTrue(countCreations()=50,"Check5, at end, countCreations() = 50")
1694+
Assert.IsTrue(countInvaldiationHandlersAdded()=50,"Check5, at end, countCreations() = 50")
16771695
ClearLanguageServiceRootCachesAndCollectAndFinalizeAllTransients(this.VS)
1678-
Assert.IsTrue(countDisposals()=50,"Check6b, at end, countDisposals() = 50 when clearing")
1696+
Assert.IsTrue(countDisposals()=50,"Check6b, at end, countDisposals() = 50 after explicit clearing")
1697+
Assert.IsTrue(countInvaldiationHandlersRemoved()=50,"Check5, at end, countInvaldiationHandlersRemoved() = 50 after explicit cleraring")
16791698

16801699
[<Test>]
16811700
[<Category("TypeProvider")>]

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp