1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 10:12:54 +08:00

Add flag to guard against deadlocks during blocking operations

This commit is contained in:
Dean Herbert 2022-01-26 17:09:28 +09:00
parent 11f0f3c17d
commit 791ea0308f

View File

@ -89,10 +89,15 @@ namespace osu.Game.Database
private Realm? updateRealm;
private bool isSendingNotificationResetEvents;
public Realm Realm => ensureUpdateRealm();
private Realm ensureUpdateRealm()
{
if (isSendingNotificationResetEvents)
throw new InvalidOperationException("Cannot retrieve a realm context from a notification callback during a blocking operation.");
if (!ThreadSafety.IsUpdateThread)
throw new InvalidOperationException(@$"Use {nameof(getRealmInstance)} when performing realm operations from a non-update thread");
@ -614,8 +619,20 @@ namespace osu.Game.Database
// calls above.
syncContext?.Send(_ =>
{
foreach (var action in notificationsResetMap.Values)
action();
// Flag ensures that we don't get in a deadlocked scenario due to a callback attempting to access `RealmAccess.Realm` or `RealmAccess.Run`
// and hitting `realmRetrievalLock` a second time. Generally such usages should not exist, and as such we throw when an attempt is made
// to use in this fashion.
isSendingNotificationResetEvents = true;
try
{
foreach (var action in notificationsResetMap.Values)
action();
}
finally
{
isSendingNotificationResetEvents = false;
}
}, null);
const int sleep_length = 200;