Don't capture AsyncLocals into MemoryCache timer (dotnet/corefx#26077)
authorBen Adams <thundercat@illyriad.co.uk>
Thu, 18 Jan 2018 02:29:18 +0000 (02:29 +0000)
committerKarel Zikmund <karelz@microsoft.com>
Thu, 18 Jan 2018 02:29:18 +0000 (18:29 -0800)
Don't capture AsyncLocals into MemoryCache timer

Commit migrated from https://github.com/dotnet/corefx/commit/7882fbe52865f59f20defa4558490be7ec3dc6cb

src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/CacheExpires.cs
src/libraries/System.Runtime.Caching/src/System/Runtime/Caching/MemoryCacheStatistics.cs

index f296a8d..9dcd141 100644 (file)
@@ -896,8 +896,26 @@ namespace System.Runtime.Caching
                 {
                     DateTime utcNow = DateTime.UtcNow;
                     TimeSpan due = _tsPerBucket - (new TimeSpan(utcNow.Ticks % _tsPerBucket.Ticks));
-                    Timer timer = new Timer(new TimerCallback(this.TimerCallback), null,
+                    Timer timer;
+                    // Don't capture the current ExecutionContext and its AsyncLocals onto the timer causing them to live forever
+                    bool restoreFlow = false;
+                    try
+                    {
+                        if (!ExecutionContext.IsFlowSuppressed())
+                        {
+                            ExecutionContext.SuppressFlow();
+                            restoreFlow = true;
+                        }
+
+                        timer = new Timer(new TimerCallback(this.TimerCallback), null,
                             due.Ticks / TimeSpan.TicksPerMillisecond, _tsPerBucket.Ticks / TimeSpan.TicksPerMillisecond);
+                    }
+                    finally
+                    {
+                        // Restore the current ExecutionContext
+                        if (restoreFlow)
+                            ExecutionContext.RestoreFlow();
+                    }
                     _timerHandleRef = new GCHandleRef<Timer>(timer);
 
                     Dbg.Trace("Cache", "Cache expiration timer created.");
index c8446a3..7b1430d 100644 (file)
@@ -155,7 +155,26 @@ namespace System.Runtime.Caching
             try
             {
                 _cacheMemoryMonitor = new CacheMemoryMonitor(_memoryCache, _configCacheMemoryLimitMegabytes);
-                Timer timer = new Timer(new TimerCallback(CacheManagerTimerCallback), null, _configPollingInterval, _configPollingInterval);
+                Timer timer;
+                // Don't capture the current ExecutionContext and its AsyncLocals onto the timer causing them to live forever
+                bool restoreFlow = false;
+                try
+                {
+                    if (!ExecutionContext.IsFlowSuppressed())
+                    {
+                        ExecutionContext.SuppressFlow();
+                        restoreFlow = true;
+                    }
+
+                    timer = new Timer(new TimerCallback(CacheManagerTimerCallback), null, _configPollingInterval, _configPollingInterval);
+                }
+                finally
+                {
+                    // Restore the current ExecutionContext
+                    if (restoreFlow)
+                        ExecutionContext.RestoreFlow();
+                }
+
                 _timerHandleRef = new GCHandleRef<Timer>(timer);
                 dispose = false;
             }