From 16a4b426dc98d5ead954195ba0a4b76845ee41d4 Mon Sep 17 00:00:00 2001 From: Michael Tsibelman Date: Mon, 24 Jul 2017 12:43:38 +0300 Subject: [PATCH] Add locking to Servicese dispose (#58) Make dispose safe --- .../Service/GigyaServiceHost.cs | 17 ++++++-- .../MicrodotServiceHost.cs | 39 +++++++++++++------ .../MicrodotOrleansServiceHost.cs | 24 +++++++++--- SolutionVersion.cs | 6 +-- 4 files changed, 63 insertions(+), 23 deletions(-) diff --git a/Gigya.Microdot.Hosting/Service/GigyaServiceHost.cs b/Gigya.Microdot.Hosting/Service/GigyaServiceHost.cs index 6cd8c165..b7300310 100644 --- a/Gigya.Microdot.Hosting/Service/GigyaServiceHost.cs +++ b/Gigya.Microdot.Hosting/Service/GigyaServiceHost.cs @@ -264,9 +264,9 @@ protected virtual void Dispose(bool disposing) if (disposed) return; - StopEvent?.Dispose(); - WindowsService?.Dispose(); - MonitoredShutdownProcess?.Dispose(); + SafeDispose(StopEvent); + SafeDispose(WindowsService); + SafeDispose(MonitoredShutdownProcess); disposed = true; } @@ -278,6 +278,17 @@ public void Dispose() GC.SuppressFinalize(this); } + protected void SafeDispose(IDisposable disposable) + { + try + { + disposable?.Dispose(); + } + catch (Exception e) + { + Trace.TraceError(e.ToString()); + } + } private class DelegatingServiceBase : ServiceBase diff --git a/Gigya.Microdot.Ninject.Host/MicrodotServiceHost.cs b/Gigya.Microdot.Ninject.Host/MicrodotServiceHost.cs index cdd14f82..6fe38dda 100644 --- a/Gigya.Microdot.Ninject.Host/MicrodotServiceHost.cs +++ b/Gigya.Microdot.Ninject.Host/MicrodotServiceHost.cs @@ -21,6 +21,7 @@ #endregion using System; +using System.Diagnostics; using Gigya.Microdot.Hosting.HttpService; using Gigya.Microdot.Hosting.Service; using Gigya.Microdot.Interfaces; @@ -40,6 +41,8 @@ namespace Gigya.Microdot.Ninject.Host public abstract class MicrodotServiceHost : GigyaServiceHost { private bool disposed; + + private readonly object disposeLockHandale = new object(); private IKernel Kernel { get; set; } @@ -116,15 +119,6 @@ protected virtual IKernel CreateKernel() } - protected override void Dispose(bool disposing) - { - if(disposed) - return; - Kernel?.Dispose(); - disposed = true; - base.Dispose(disposing); - } - /// /// Used to configure Kernel in abstract base-classes, which should apply to any concrete service that inherits from it. /// Should be overridden when creating a base-class that should include common behaviour for a family of services, without @@ -157,9 +151,32 @@ protected virtual void PreConfigure(IKernel kernel) /// method. /// protected override void OnStop() + { + Dispose(); + } + + + protected override void Dispose(bool disposing) { - Listener.Dispose(); - Kernel.Dispose(); + lock (disposeLockHandale) + { + try + { + if(disposed) + return; + + SafeDispose(Listener); + + if(!Kernel.IsDisposed) + SafeDispose(Kernel); + + base.Dispose(disposing); + } + finally + { + disposed = true; + } + } } } } diff --git a/Gigya.Microdot.Orleans.Ninject.Host/MicrodotOrleansServiceHost.cs b/Gigya.Microdot.Orleans.Ninject.Host/MicrodotOrleansServiceHost.cs index 9bb1093e..58e8b7d1 100644 --- a/Gigya.Microdot.Orleans.Ninject.Host/MicrodotOrleansServiceHost.cs +++ b/Gigya.Microdot.Orleans.Ninject.Host/MicrodotOrleansServiceHost.cs @@ -165,14 +165,26 @@ protected override void OnStop() Dispose(); } - + private readonly object lockHandale=new object(); protected override void Dispose(bool disposing) { - if (disposed) - return; - Kernel?.Dispose(); - disposed = true; - base.Dispose(disposing); + lock(lockHandale) + { + try + { + if (disposed) + return; + + if (!Kernel.IsDisposed) + SafeDispose( Kernel); + + base.Dispose(disposing); + } + finally + { + disposed = true; + } + } } } } diff --git a/SolutionVersion.cs b/SolutionVersion.cs index fd6e32a9..e3071fca 100644 --- a/SolutionVersion.cs +++ b/SolutionVersion.cs @@ -28,9 +28,9 @@ [assembly: AssemblyCopyright("© 2017 Gigya Inc.")] [assembly: AssemblyDescription("Microdot Framework")] -[assembly: AssemblyVersion("1.2.2.0")] -[assembly: AssemblyFileVersion("1.2.2.0")] -[assembly: AssemblyInformationalVersion("1.2.2.0")] +[assembly: AssemblyVersion("1.2.3.0")] +[assembly: AssemblyFileVersion("1.2.3.0")] +[assembly: AssemblyInformationalVersion("1.2.3.0")] // Setting ComVisible to false makes the types in this assembly not visible