From b61df304ea36ee0c4496586a1f87a4e6a4549c1a Mon Sep 17 00:00:00 2001 From: Ahmed Zamil Date: Fri, 11 Dec 2020 01:17:15 +0300 Subject: [PATCH] mem leak --- .../Esiur.Stores.EntityCore.csproj | 4 +- Esiur.Stores.EntityCore/EsiurPlugin.cs | 2 +- Esiur.Stores.EntityCore/EsiurProxyRewrite.cs | 8 +- .../Properties/launchSettings.json | 3 +- .../Esiur.Stores.MongoDB.csproj | 2 +- Esiur/Data/AutoList.cs | 7 +- Esiur/Esiur.csproj | 4 +- Esiur/Net/IIP/DistributedConnection.cs | 11 +- .../Net/IIP/DistributedConnectionProtocol.cs | 111 ++++++++++++++---- 9 files changed, 110 insertions(+), 42 deletions(-) diff --git a/Esiur.Stores.EntityCore/Esiur.Stores.EntityCore.csproj b/Esiur.Stores.EntityCore/Esiur.Stores.EntityCore.csproj index 876af97..61f4312 100644 --- a/Esiur.Stores.EntityCore/Esiur.Stores.EntityCore.csproj +++ b/Esiur.Stores.EntityCore/Esiur.Stores.EntityCore.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 Esiur.Stores.EntityCore Ahmed Kh. Zamil Esiur Foundation @@ -12,7 +12,7 @@ - + diff --git a/Esiur.Stores.EntityCore/EsiurPlugin.cs b/Esiur.Stores.EntityCore/EsiurPlugin.cs index 590f79c..a29e5f4 100644 --- a/Esiur.Stores.EntityCore/EsiurPlugin.cs +++ b/Esiur.Stores.EntityCore/EsiurPlugin.cs @@ -49,7 +49,7 @@ namespace Esiur.Stores.EntityCore public ConventionSet ModifyConventions(ConventionSet conventionSet) { var extension = _options.FindExtension(); - conventionSet.ModelFinalizedConventions.Add(new EsiurProxyRewrite( + conventionSet.ModelFinalizingConventions.Add(new EsiurProxyRewrite( extension, _conventionSetBuilderDependencies)); return conventionSet; diff --git a/Esiur.Stores.EntityCore/EsiurProxyRewrite.cs b/Esiur.Stores.EntityCore/EsiurProxyRewrite.cs index 06ca2c6..73a10cc 100644 --- a/Esiur.Stores.EntityCore/EsiurProxyRewrite.cs +++ b/Esiur.Stores.EntityCore/EsiurProxyRewrite.cs @@ -40,7 +40,7 @@ using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Esiur.Stores.EntityCore { - public class EsiurProxyRewrite : IModelFinalizedConvention + public class EsiurProxyRewrite : IModelFinalizingConvention { private static readonly MethodInfo _createInstance = typeof(EsiurProxyRewrite).GetTypeInfo().GetDeclaredMethod(nameof(EsiurProxyRewrite.CreateInstance)); @@ -94,7 +94,7 @@ namespace Esiur.Stores.EntityCore } - public void ProcessModelFinalized(IConventionModelBuilder modelBuilder, IConventionContext context) + public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext context) { foreach (var entityType in modelBuilder.Metadata.GetEntityTypes()) { @@ -106,7 +106,7 @@ namespace Esiur.Stores.EntityCore var binding = (InstantiationBinding)entityType[CoreAnnotationNames.ConstructorBinding]; #pragma warning restore EF1001 // Internal EF Core API usage. if (binding == null) - _directBindingConvention.ProcessModelFinalized(modelBuilder, context); + _directBindingConvention.ProcessModelFinalizing(modelBuilder, context); #pragma warning disable EF1001 // Internal EF Core API usage. binding = (InstantiationBinding)entityType[CoreAnnotationNames.ConstructorBinding]; @@ -145,5 +145,7 @@ namespace Esiur.Stores.EntityCore } } + + } } diff --git a/Esiur.Stores.EntityCore/Properties/launchSettings.json b/Esiur.Stores.EntityCore/Properties/launchSettings.json index a8ff82e..c14252c 100644 --- a/Esiur.Stores.EntityCore/Properties/launchSettings.json +++ b/Esiur.Stores.EntityCore/Properties/launchSettings.json @@ -1,8 +1,7 @@ { "profiles": { "Esiur.Stores.EntityCore": { - "commandName": "Project", - "commandLineArgs": "--migrate" + "commandName": "Project" } } } \ No newline at end of file diff --git a/Esiur.Stores.MongoDB/Esiur.Stores.MongoDB.csproj b/Esiur.Stores.MongoDB/Esiur.Stores.MongoDB.csproj index 301679c..93a5be4 100644 --- a/Esiur.Stores.MongoDB/Esiur.Stores.MongoDB.csproj +++ b/Esiur.Stores.MongoDB/Esiur.Stores.MongoDB.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 Ahmed Kh. Zamil Esiur Esiur MongoDB Store diff --git a/Esiur/Data/AutoList.cs b/Esiur/Data/AutoList.cs index a598912..ac8c501 100644 --- a/Esiur/Data/AutoList.cs +++ b/Esiur/Data/AutoList.cs @@ -62,17 +62,20 @@ namespace Esiur.Data public void Sort() { + lock(syncRoot) list.Sort(); } public void Sort(IComparer comparer) { - list.Sort(comparer); + lock (syncRoot) + list.Sort(comparer); } public void Sort(Comparison comparison) { - list.Sort(comparison); + lock (syncRoot) + list.Sort(comparison); } public IEnumerable Where(Func predicate) diff --git a/Esiur/Esiur.csproj b/Esiur/Esiur.csproj index 0edc49f..4a7096a 100644 --- a/Esiur/Esiur.csproj +++ b/Esiur/Esiur.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 Distributed Resources Platform Ahmed Kh. Zamil https://github.com/Esiur/Esiur-dotnet/blob/master/LICENSE @@ -52,7 +52,7 @@ - + diff --git a/Esiur/Net/IIP/DistributedConnection.cs b/Esiur/Net/IIP/DistributedConnection.cs index 13ba8c8..32be72d 100644 --- a/Esiur/Net/IIP/DistributedConnection.cs +++ b/Esiur/Net/IIP/DistributedConnection.cs @@ -62,9 +62,6 @@ namespace Esiur.Net.IIP Session session; - - List attachedResources = new List(); - AsyncReply openReply; byte[] localPasswordOrToken; @@ -291,8 +288,8 @@ namespace Esiur.Net.IIP void init() { - var q = queue; - q.Then((x) => + //var q = queue; + queue.Then((x) => { if (x.Type == DistributedResourceQueueItem.DistributedResourceQueueItemType.Event) x.Resource._EmitEventByIndex(x.Index, (object[])x.Value); @@ -308,6 +305,7 @@ namespace Esiur.Net.IIP public override void Destroy() { + UnsubscribeAll(); this.OnReady = null; this.OnError = null; base.Destroy(); @@ -1146,13 +1144,14 @@ namespace Esiur.Net.IIP Server?.Membership.Logout(session); Warehouse.Remove(this); ready = false; + UnsubscribeAll(); } } /* public AsyncBag Children(IResource resource) { - if (Codec.IsLocalResource(resource, this)) + if (Codec.IsLocalReso turce(resource, this)) return (resource as DistributedResource).children.Where(x => x.GetType() == typeof(T)).Select(x => (T)x); return null; diff --git a/Esiur/Net/IIP/DistributedConnectionProtocol.cs b/Esiur/Net/IIP/DistributedConnectionProtocol.cs index 6199a8e..a923929 100644 --- a/Esiur/Net/IIP/DistributedConnectionProtocol.cs +++ b/Esiur/Net/IIP/DistributedConnectionProtocol.cs @@ -54,6 +54,9 @@ namespace Esiur.Net.IIP volatile uint callbackCounter = 0; + List subscriptions = new List(); + object subscriptionsLock = new object(); + AsyncQueue queue = new AsyncQueue(); /// @@ -459,10 +462,14 @@ namespace Esiur.Net.IIP var r = res as IResource; // unsubscribe - r.Instance.ResourceEventOccurred -= Instance_EventOccurred; - r.Instance.CustomResourceEventOccurred -= Instance_CustomEventOccurred; - r.Instance.ResourceModified -= Instance_PropertyModified; - r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed; + Unsubscribe(r); + + //r.Instance.ResourceEventOccurred -= Instance_EventOccurred; + //r.Instance.CustomResourceEventOccurred -= Instance_CustomEventOccurred; + //r.Instance.ResourceModified -= Instance_PropertyModified; + //r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed; + + // r.Instance.Children.OnAdd -= Children_OnAdd; // r.Instance.Children.OnRemoved -= Children_OnRemoved; @@ -471,7 +478,7 @@ namespace Esiur.Net.IIP // Console.WriteLine("Attach {0} {1}", r.Instance.Link, r.Instance.Id); // add it to attached resources so GC won't remove it from memory - attachedResources.Add(r); + ///attachedResources.Add(r); var link = DC.ToBytes(r.Instance.Link); @@ -501,10 +508,13 @@ namespace Esiur.Net.IIP // subscribe - r.Instance.ResourceEventOccurred += Instance_EventOccurred; - r.Instance.CustomResourceEventOccurred += Instance_CustomEventOccurred; - r.Instance.ResourceModified += Instance_PropertyModified; - r.Instance.ResourceDestroyed += Instance_ResourceDestroyed; + //r.Instance.ResourceEventOccurred += Instance_EventOccurred; + //r.Instance.CustomResourceEventOccurred += Instance_CustomEventOccurred; + //r.Instance.ResourceModified += Instance_PropertyModified; + //r.Instance.ResourceDestroyed += Instance_ResourceDestroyed; + + Subscribe(r); + //r.Instance.Children.OnAdd += Children_OnAdd; //r.Instance.Children.OnRemoved += Children_OnRemoved; @@ -582,20 +592,25 @@ namespace Esiur.Net.IIP { var r = res as IResource; // unsubscribe - r.Instance.ResourceEventOccurred -= Instance_EventOccurred; - r.Instance.CustomResourceEventOccurred -= Instance_CustomEventOccurred; - r.Instance.ResourceModified -= Instance_PropertyModified; - r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed; + Unsubscribe(r); + + //r.Instance.ResourceEventOccurred -= Instance_EventOccurred; + //r.Instance.CustomResourceEventOccurred -= Instance_CustomEventOccurred; + //r.Instance.ResourceModified -= Instance_PropertyModified; + //r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed; + //r.Instance.Children.OnAdd -= Children_OnAdd; //r.Instance.Children.OnRemoved -= Children_OnRemoved; //r.Instance.Attributes.OnModified -= Attributes_OnModified; // subscribe - r.Instance.ResourceEventOccurred += Instance_EventOccurred; - r.Instance.CustomResourceEventOccurred += Instance_CustomEventOccurred; - r.Instance.ResourceModified += Instance_PropertyModified; - r.Instance.ResourceDestroyed += Instance_ResourceDestroyed; + //r.Instance.ResourceEventOccurred += Instance_EventOccurred; + //r.Instance.CustomResourceEventOccurred += Instance_CustomEventOccurred; + //r.Instance.ResourceModified += Instance_PropertyModified; + //r.Instance.ResourceDestroyed += Instance_ResourceDestroyed; + + Subscribe(r); //r.Instance.Children.OnAdd += Children_OnAdd; //r.Instance.Children.OnRemoved += Children_OnRemoved; @@ -621,14 +636,16 @@ namespace Esiur.Net.IIP { if (res != null) { - var r = res as IResource; - r.Instance.ResourceEventOccurred -= Instance_EventOccurred; - r.Instance.CustomResourceEventOccurred -= Instance_CustomEventOccurred; - r.Instance.ResourceModified -= Instance_PropertyModified; - r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed; + //var r = res as IResource; + //r.Instance.ResourceEventOccurred -= Instance_EventOccurred; + //r.Instance.CustomResourceEventOccurred -= Instance_CustomEventOccurred; + //r.Instance.ResourceModified -= Instance_PropertyModified; + //r.Instance.ResourceDestroyed -= Instance_ResourceDestroyed; + + Unsubscribe(res); // remove from attached resources - attachedResources.Remove(res); + //attachedResources.Remove(res); // reply ok SendReply(IIPPacket.IIPPacketAction.DetachResource, callback).Done(); @@ -2190,12 +2207,60 @@ namespace Esiur.Net.IIP return reply; } + private void Subscribe(IResource resource) + { + lock (subscriptionsLock) + { + resource.Instance.ResourceEventOccurred += Instance_EventOccurred; + resource.Instance.CustomResourceEventOccurred += Instance_CustomEventOccurred; + resource.Instance.ResourceModified += Instance_PropertyModified; + resource.Instance.ResourceDestroyed += Instance_ResourceDestroyed; + + subscriptions.Add(resource); + } + } + + private void Unsubscribe(IResource resource) + { + lock (subscriptionsLock) + { + // do something with the list... + resource.Instance.ResourceEventOccurred -= Instance_EventOccurred; + resource.Instance.CustomResourceEventOccurred -= Instance_CustomEventOccurred; + resource.Instance.ResourceModified -= Instance_PropertyModified; + resource.Instance.ResourceDestroyed -= Instance_ResourceDestroyed; + + subscriptions.Remove(resource); + } + + } + + private void UnsubscribeAll() + { + lock(subscriptionsLock) + { + foreach(var resource in subscriptions) + { + resource.Instance.ResourceEventOccurred -= Instance_EventOccurred; + resource.Instance.CustomResourceEventOccurred -= Instance_CustomEventOccurred; + resource.Instance.ResourceModified -= Instance_PropertyModified; + resource.Instance.ResourceDestroyed -= Instance_ResourceDestroyed; + } + + subscriptions.Clear(); + } + } + private void Instance_ResourceDestroyed(IResource resource) { + + Unsubscribe(resource); // compose the packet SendEvent(IIPPacket.IIPPacketEvent.ResourceDestroyed) .AddUInt32(resource.Instance.Id) .Done(); + + } private void Instance_PropertyModified(IResource resource, string name, object newValue)