Skip to content

Commit

Permalink
Fix for CancellationTokenSource not disposed #1234
Browse files Browse the repository at this point in the history
  • Loading branch information
louthy committed Aug 7, 2023
1 parent f62b55c commit 886daea
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 23 deletions.
71 changes: 49 additions & 22 deletions LanguageExt.Core/Effects/Aff/Aff.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,27 +100,35 @@ public Eff<RT, Eff<Unit>> Fork()
var reg = env.CancellationToken.Register(() => lenv.CancellationTokenSource.Cancel());
// Run
ignore(t(lenv).Iter(_ => Dispose()));
ignore(Go(t, lenv, reg));
// Return an effect that cancels the fire-and-forget expression
return Eff<Unit>(() =>
{
lenv.CancellationTokenSource.Cancel();
Dispose();
return unit;
});
void Dispose()
{
try
{
reg.Dispose();
}
catch
{
}
}
return Eff(() =>
{
try
{
lenv.CancellationTokenSource.Cancel();
}
catch
{
// The token-source might have already been disposed, so let's ignore that error
}
return unit;
});
});

async Task Go(Func<RT, ValueTask<Fin<A>>> thunk, RT lenv, CancellationTokenRegistration reg)
{
try
{
await thunk(lenv).ConfigureAwait(false);
}
finally
{
lenv.CancellationTokenSource.Dispose();
reg.Dispose();
}
}
}

/// <summary>
Expand Down Expand Up @@ -177,20 +185,39 @@ public Aff<RT, A> Timeout(TimeSpan timeoutDelay)
using var delayTokSrc = new CancellationTokenSource();
var lenv = env.LocalCancel;
var delay = Task.Delay(timeoutDelay, delayTokSrc.Token);
var task = t(lenv).AsTask();
var completed = await Task.WhenAny(new Task[] {delay, task}).ConfigureAwait(false);
var task = Go(t, lenv);
var completed = await Task.WhenAny(delay, task).ConfigureAwait(false);
if (completed == delay)
{
lenv.CancellationTokenSource.Cancel();
return FinFail<A>(Errors.TimedOut);
try
{
lenv.CancellationTokenSource.Cancel();
}
catch
{
// The token-source might have already been disposed, so let's ignore that error
}
return FinFail<A>(Errors.TimedOut);
}
else
{
delayTokSrc.Cancel();
return await task.ConfigureAwait(false);
}
});

async Task<Fin<A>> Go(Func<RT, ValueTask<Fin<A>>> thunk, RT lenv)
{
try
{
return await thunk(lenv).ConfigureAwait(false);
}
finally
{
lenv.CancellationTokenSource.Dispose();
}
}
}

[Pure, MethodImpl(Opt.Default)]
Expand Down
1 change: 0 additions & 1 deletion LanguageExt.Core/Effects/Eff/Eff.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using static LanguageExt.Prelude;
using System.Diagnostics.Contracts;
using System.Runtime.CompilerServices;
using LanguageExt.Thunks;

namespace LanguageExt
{
Expand Down

0 comments on commit 886daea

Please sign in to comment.