Skip to content

Commit fb6d9bd

Browse files
committed
fix: Harden AsyncWriteCollection against edge cases
- Guard queuedBytes decrement with Remove() return value check, preventing queuedBytes from going negative if Remove is called for an already-removed key - Catch unhandled exceptions in Task.Run body to prevent UnobservedTaskException: since Remove() in the finally block removes the task from the collection before the exception propagates, AwaitAllCurrentTasks() would never observe it - Add null filter in AwaitAllCurrentTasks for defensive safety
1 parent 61a05ff commit fb6d9bd

File tree

1 file changed

+15
-4
lines changed

1 file changed

+15
-4
lines changed

src/Imazen.HybridCache/AsyncWriteCollection.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,17 @@ public AsyncWrite Get(string key) {
3838
}
3939

4040
/// <summary>
41-
/// Removes the specified object based on its relativePath and modifiedDateUtc values.
41+
/// Removes the specified object based on its key and decrements queuedBytes.
42+
/// Only decrements if the key was actually present, preventing queuedBytes from going negative.
4243
/// </summary>
4344
/// <param name="w"></param>
4445
private void Remove(AsyncWrite w) {
4546
lock (sync)
4647
{
47-
c.Remove(w.Key);
48-
queuedBytes -= w.GetEntrySizeInMemory();
48+
if (c.Remove(w.Key))
49+
{
50+
queuedBytes -= w.GetEntrySizeInMemory();
51+
}
4952
}
5053
}
5154

@@ -75,6 +78,14 @@ public AsyncQueueResult Queue(AsyncWrite w, Func<AsyncWrite, Task> writerDelegat
7578
{
7679
await writerDelegate(w);
7780
}
81+
catch
82+
{
83+
// Caller's writerDelegate is expected to handle its own exceptions.
84+
// Catch here to prevent unobserved task exceptions: since Remove()
85+
// in the finally block removes this task from the collection before
86+
// the exception propagates, AwaitAllCurrentTasks() would never
87+
// observe it, leading to UnobservedTaskException on the finalizer thread.
88+
}
7889
finally
7990
{
8091
Remove(w);
@@ -88,7 +99,7 @@ public Task AwaitAllCurrentTasks()
8899
{
89100
lock (sync)
90101
{
91-
var tasks = c.Values.Select(w => w.RunningTask).ToArray();
102+
var tasks = c.Values.Select(w => w.RunningTask).Where(t => t != null).ToArray();
92103
return Task.WhenAll(tasks);
93104
}
94105
}

0 commit comments

Comments
 (0)