Skip to content

Commit

Permalink
RavenDB-21888 Make sure the timer callback won't start before we assi…
Browse files Browse the repository at this point in the history
…gn the timer instance to internal state. Catch and ignore exceptions on the timer disposal in the callback.
  • Loading branch information
arekpalinski committed Jan 8, 2024
1 parent 84ca565 commit 4a484f8
Showing 1 changed file with 32 additions and 8 deletions.
40 changes: 32 additions & 8 deletions src/Raven.Client/Util/WeakReferencingTimer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ public WeakReferencingTimer(WeakReferencingTimerCallback callback, object state,
Callback = new WeakReference<WeakReferencingTimerCallback>(callback)
};

_timer = new Timer(StaticCallback, internalTimerState, dueTime, period);
const uint infinite = unchecked((uint)-1); // register the timer but do not activate it yet

internalTimerState.Timer = _timer;
_timer = new Timer(StaticCallback, internalTimerState, infinite, infinite);

internalTimerState.Timer = _timer; // assign timer instance to the state

_timer.Change(dueTime, period); // now let's activate the timer
}

private static void StaticCallback(object state)
Expand All @@ -32,13 +36,33 @@ private static void StaticCallback(object state)

if (timerState.State is not null && timerState.State.TryGetTarget(out stateObj) == false)
{
timerState.Timer.Dispose();
try
{
timerState.Timer.Dispose();
}
catch (Exception e)
{
#if DEBUG
Console.WriteLine($"Disposal of timer instance got an exception:{Environment.NewLine}{e}");
#endif
// ignored
}
return;
}

if (timerState.Callback.TryGetTarget(out var callback) == false)
{
timerState.Timer.Dispose();
try
{
timerState.Timer.Dispose();
}
catch (Exception e)
{
#if DEBUG
Console.WriteLine($"Disposal of timer instance got an exception:{Environment.NewLine}{e}");
#endif
// ignored
}
return;
}

Expand All @@ -52,13 +76,13 @@ private class TimerState
public Timer Timer;
}

public void Dispose()
public void Change(TimeSpan dueTime, TimeSpan period)
{
_timer?.Dispose();
_timer?.Change(dueTime, period);
}

public void Change(TimeSpan dueTime, TimeSpan period)
public void Dispose()
{
_timer?.Change(dueTime, period);
_timer?.Dispose();
}
}

0 comments on commit 4a484f8

Please sign in to comment.