mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-19 06:54:19 +01:00
Fix crash if DelayedTaskScheduler has too big timestamp
This commit is contained in:
@@ -3030,7 +3030,9 @@ namespace BTCPayServer.Tests
|
|||||||
});
|
});
|
||||||
var invoiceRepo = tester.PayTester.GetService<InvoiceRepository>();
|
var invoiceRepo = tester.PayTester.GetService<InvoiceRepository>();
|
||||||
var invoice = await invoiceRepo.GetInvoice("Q7RqoHLngK9svM4MgRyi9y");
|
var invoice = await invoiceRepo.GetInvoice("Q7RqoHLngK9svM4MgRyi9y");
|
||||||
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
var p = invoice.Payments.First(p => p.Id == "26c879f3d27a894a62f8730c84205ac9dec38b7bbc0a11ccc0c196d1259b25aa-1");
|
var p = invoice.Payments.First(p => p.Id == "26c879f3d27a894a62f8730c84205ac9dec38b7bbc0a11ccc0c196d1259b25aa-1");
|
||||||
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
var details = p.GetDetails<BitcoinLikePaymentData>(handlers.GetBitcoinHandler("BTC"));
|
var details = p.GetDetails<BitcoinLikePaymentData>(handlers.GetBitcoinHandler("BTC"));
|
||||||
Assert.Equal("6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d", details.AssetId.ToString());
|
Assert.Equal("6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d", details.AssetId.ToString());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,25 @@ namespace BTCPayServer.Services
|
|||||||
{
|
{
|
||||||
Logger = logger;
|
Logger = logger;
|
||||||
}
|
}
|
||||||
record class TimerState(string Key, Func<Task> Act);
|
record class TimerState(string Key, Func<Task> Act, DateTimeOffset ExecuteAt)
|
||||||
|
{
|
||||||
|
internal TimeSpan NextWait()
|
||||||
|
{
|
||||||
|
var due = ExecuteAt - DateTimeOffset.UtcNow;
|
||||||
|
if (due < TimeSpan.Zero)
|
||||||
|
due = TimeSpan.Zero;
|
||||||
|
// Max timer needed, else dotnet crash
|
||||||
|
if (due > MaxTimer)
|
||||||
|
due = MaxTimer;
|
||||||
|
return due;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private readonly Dictionary<string, Timer> _timers = new();
|
private readonly Dictionary<string, Timer> _timers = new();
|
||||||
bool disposed = false;
|
bool disposed = false;
|
||||||
|
|
||||||
public ILogger<DelayedTaskScheduler> Logger { get; }
|
public ILogger<DelayedTaskScheduler> Logger { get; }
|
||||||
|
static TimeSpan MaxTimer = TimeSpan.FromMilliseconds(4294967294);
|
||||||
public void Schedule(string key, DateTimeOffset executeAt, Func<Task> act)
|
public void Schedule(string key, DateTimeOffset executeAt, Func<Task> act)
|
||||||
{
|
{
|
||||||
lock (_timers)
|
lock (_timers)
|
||||||
@@ -33,23 +46,26 @@ namespace BTCPayServer.Services
|
|||||||
existing.Dispose();
|
existing.Dispose();
|
||||||
_timers.Remove(key);
|
_timers.Remove(key);
|
||||||
}
|
}
|
||||||
var due = executeAt - DateTimeOffset.UtcNow;
|
|
||||||
if (due < TimeSpan.Zero)
|
var state = new TimerState(key, act, executeAt);
|
||||||
due = TimeSpan.Zero;
|
var timer = new Timer(TimerCallback, state, Timeout.Infinite, Timeout.Infinite);
|
||||||
var timer = new Timer(TimerCallback, new TimerState(key, act), Timeout.Infinite, Timeout.Infinite);
|
|
||||||
_timers.Add(key, timer);
|
_timers.Add(key, timer);
|
||||||
timer.Change((long)due.TotalMilliseconds, (long)Timeout.Infinite);
|
timer.Change(state.NextWait(), Timeout.InfiniteTimeSpan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void TimerCallback(object? state)
|
void TimerCallback(object? state)
|
||||||
{
|
{
|
||||||
var s = (TimerState)state!;
|
var s = (TimerState)state!;
|
||||||
Task.Run(async () =>
|
Task.Run(async () =>
|
||||||
{
|
{
|
||||||
|
bool run = s.NextWait() == TimeSpan.Zero;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await s.Act();
|
if (run)
|
||||||
|
await s.Act();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -62,7 +78,10 @@ namespace BTCPayServer.Services
|
|||||||
{
|
{
|
||||||
if (_timers.TryGetValue(s.Key, out timer))
|
if (_timers.TryGetValue(s.Key, out timer))
|
||||||
{
|
{
|
||||||
_timers.Remove(s.Key);
|
if (run)
|
||||||
|
_timers.Remove(s.Key);
|
||||||
|
else
|
||||||
|
timer.Change(s.NextWait(), Timeout.InfiniteTimeSpan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timer?.Dispose();
|
timer?.Dispose();
|
||||||
@@ -80,5 +99,5 @@ namespace BTCPayServer.Services
|
|||||||
_timers.Clear();
|
_timers.Clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user