From db99baac354d08196a9e64790fa552eb14e932d5 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Fri, 7 Sep 2018 22:08:08 +0100 Subject: [PATCH] Don't capture AsyncLocals onto Timers (#2904) --- src/Common/TimerAwaitable.cs | 21 ++++++++++++++++++- .../Internal/AckHandler.cs | 21 ++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/Common/TimerAwaitable.cs b/src/Common/TimerAwaitable.cs index d2e0005bcf..ee6cb0fd23 100644 --- a/src/Common/TimerAwaitable.cs +++ b/src/Common/TimerAwaitable.cs @@ -40,7 +40,26 @@ namespace Microsoft.AspNetCore.Internal if (_timer == null) { - _timer = new Timer(state => ((TimerAwaitable)state).Tick(), this, _dueTime, _period); + // Don't capture the current ExecutionContext and its AsyncLocals onto the timer + bool restoreFlow = false; + try + { + if (!ExecutionContext.IsFlowSuppressed()) + { + ExecutionContext.SuppressFlow(); + restoreFlow = true; + } + + _timer = new Timer(state => ((TimerAwaitable)state).Tick(), this, _dueTime, _period); + } + finally + { + // Restore the current ExecutionContext + if (restoreFlow) + { + ExecutionContext.RestoreFlow(); + } + } } } } diff --git a/src/Microsoft.AspNetCore.SignalR.Redis/Internal/AckHandler.cs b/src/Microsoft.AspNetCore.SignalR.Redis/Internal/AckHandler.cs index b455d0427d..c5502e28a2 100644 --- a/src/Microsoft.AspNetCore.SignalR.Redis/Internal/AckHandler.cs +++ b/src/Microsoft.AspNetCore.SignalR.Redis/Internal/AckHandler.cs @@ -19,7 +19,26 @@ namespace Microsoft.AspNetCore.SignalR.Redis.Internal public AckHandler() { - _timer = new Timer(_ => CheckAcks(), state: null, dueTime: _ackInterval, period: _ackInterval); + // Don't capture the current ExecutionContext and its AsyncLocals onto the timer + bool restoreFlow = false; + try + { + if (!ExecutionContext.IsFlowSuppressed()) + { + ExecutionContext.SuppressFlow(); + restoreFlow = true; + } + + _timer = new Timer(state => ((AckHandler)state).CheckAcks(), state: this, dueTime: _ackInterval, period: _ackInterval); + } + finally + { + // Restore the current ExecutionContext + if (restoreFlow) + { + ExecutionContext.RestoreFlow(); + } + } } public Task CreateAck(int id)