-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Don't capture AsyncLocals into SQL global timers #26065
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System.Threading; | ||
|
||
namespace System.Data.Common | ||
{ | ||
internal static partial class ADP | ||
{ | ||
|
||
internal static Timer CreateGlobalTimer(TimerCallback callback, object state, int dueTime, int period) | ||
{ | ||
// Don't capture the current ExecutionContext and its AsyncLocals onto | ||
// a global timer causing them to live forever | ||
|
||
Timer timer; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can just return it from within the try block rather than declaring it here, initializing it in the try, and then returning it after the finally. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed |
||
bool restoreFlow = false; | ||
try | ||
{ | ||
if (!ExecutionContext.IsFlowSuppressed()) | ||
{ | ||
ExecutionContext.SuppressFlow(); | ||
restoreFlow = true; | ||
} | ||
|
||
timer = new Timer(callback, state, dueTime, period); | ||
} | ||
finally | ||
{ | ||
// Restore the current ExecutionContext | ||
if (restoreFlow) | ||
ExecutionContext.RestoreFlow(); | ||
} | ||
|
||
return timer; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -664,10 +664,12 @@ internal void Clear() | |
ReclaimEmancipatedObjects(); | ||
} | ||
|
||
private Timer CreateCleanupTimer() | ||
{ | ||
return (new Timer(new TimerCallback(this.CleanupCallback), null, _cleanupWait, _cleanupWait)); | ||
} | ||
private Timer CreateCleanupTimer() => | ||
ADP.CreateGlobalTimer( | ||
new TimerCallback(CleanupCallback), | ||
null, | ||
_cleanupWait, | ||
_cleanupWait); | ||
|
||
private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) | ||
{ | ||
|
@@ -728,6 +730,7 @@ private DbConnectionInternal CreateObject(DbConnection owningObject, DbConnectio | |
|
||
// timer allocation has to be done out of CER block | ||
Timer t = new Timer(new TimerCallback(this.ErrorCallback), null, Timeout.Infinite, Timeout.Infinite); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a one shot local timer; doesn't require the change |
||
|
||
bool timerIsNotDisposed; | ||
try { } | ||
finally | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -612,7 +612,9 @@ private void Restart(object unused) | |
_timeoutParam.Value = _defaultWaitforTimeout; // If success, reset to default for re-queue. | ||
AsynchronouslyQueryServiceBrokerQueue(); | ||
_errorState = false; | ||
Timer retryTimer = _retryTimer; | ||
_retryTimer = null; | ||
retryTimer?.Dispose(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not a big deal, but as long as we're doing the null check, we may as well avoid the unnecessary null write: Timer retryTimer = _retryTimer;
if (retryTimer != null)
{
_returnTimer = null;
retryTimer.Dispose();
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changed |
||
} | ||
} | ||
|
||
|
@@ -1470,4 +1472,4 @@ internal bool Stop( | |
|
||
return stopped; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I would call it UnsafeCreateTimer. Then it can be replaced by Timer.UnsafeCreate if/when it's added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed