From bd7245aecbbb8193ab5fb014fbda985b7854bfa6 Mon Sep 17 00:00:00 2001
From: Meivyn <793322+Meivyn@users.noreply.github.com>
Date: Thu, 8 Aug 2024 11:30:40 -0400
Subject: [PATCH] Fix potential thread block in
`SingleCreationValueCache.GetOrAdd`
---
.../Async/SingleCreationValueCache.cs | 22 ++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/IPA.Loader/Utilities/Async/SingleCreationValueCache.cs b/IPA.Loader/Utilities/Async/SingleCreationValueCache.cs
index ea361c55..226b0e06 100644
--- a/IPA.Loader/Utilities/Async/SingleCreationValueCache.cs
+++ b/IPA.Loader/Utilities/Async/SingleCreationValueCache.cs
@@ -71,7 +71,7 @@ namespace IPA.Utilities.Async
#endregion
///
- /// Gets a value that indicates whether this cache is empty.
+ /// Gets a value that indicates whether this cache is empty.
///
public bool IsEmpty => dict.IsEmpty;
///
@@ -143,10 +143,22 @@ namespace IPA.Utilities.Async
var cmp = (wh, default(TValue));
if (!dict.TryAdd(key, cmp))
goto retry; // someone else beat us to the punch, retry getting their value and wait for them
- var val = creator(key);
- while (!dict.TryUpdate(key, (null, val), cmp))
- throw new InvalidOperationException();
- wh.Set();
+ TValue val;
+ try
+ {
+ val = creator(key);
+ while (!dict.TryUpdate(key, (null, val), cmp))
+ throw new InvalidOperationException();
+ }
+ catch
+ {
+ dict.TryRemove(key, out _);
+ throw;
+ }
+ finally
+ {
+ wh.Set();
+ }
return val;
}
}