1
0
mirror of https://github.com/ppy/osu.git synced 2026-06-07 02:53:38 +08:00

Fix leak from no unbind from static event

This commit is contained in:
Dan Balasescu
2025-07-08 00:22:35 +09:00
Unverified
parent 8298374e59
commit d80e4b7960
+83 -88
View File
@@ -113,6 +113,9 @@ namespace osu.Game
/// </summary>
public const float SCREEN_EDGE_MARGIN = 12f;
private const double general_log_debounce = 60000;
private const string tablet_log_prefix = @"[Tablet] ";
public Toolbar Toolbar { get; private set; }
private ChatOverlay chatOverlay;
@@ -241,12 +244,26 @@ namespace osu.Game
/// </summary>
public virtual bool HideUnlicensedContent => false;
private bool tabletLogNotifyOnWarning = true;
private bool tabletLogNotifyOnError = true;
private int generalLogRecentCount;
public OsuGame(string[] args = null)
{
this.args = args;
forwardGeneralLogsToNotifications();
forwardTabletLogsToNotifications();
Logger.NewEntry += forwardGeneralLogToNotifications;
Logger.NewEntry += forwardTabletLogToNotifications;
Schedule(() =>
{
ITabletHandler tablet = Host.AvailableInputHandlers.OfType<ITabletHandler>().SingleOrDefault();
tablet?.Tablet.BindValueChanged(_ =>
{
tabletLogNotifyOnWarning = true;
tabletLogNotifyOnError = true;
}, true);
});
}
#region IOverlayManager
@@ -1010,6 +1027,9 @@ namespace osu.Game
base.Dispose(isDisposing);
SentryLogger.Dispose();
Logger.NewEntry -= forwardGeneralLogToNotifications;
Logger.NewEntry -= forwardTabletLogToNotifications;
}
protected override IDictionary<FrameworkSetting, object> GetFrameworkConfigDefaults()
@@ -1365,115 +1385,90 @@ namespace osu.Game
overlay.Depth = (float)-Clock.CurrentTime;
}
private void forwardGeneralLogsToNotifications()
private void forwardGeneralLogToNotifications(LogEntry entry)
{
int recentLogCount = 0;
if (entry.Level < LogLevel.Important || entry.Target > LoggingTarget.Database || entry.Target == null) return;
const double debounce = 60000;
if (entry.Exception is SentryOnlyDiagnosticsException)
return;
Logger.NewEntry += entry =>
const int short_term_display_limit = 3;
if (generalLogRecentCount < short_term_display_limit)
{
if (entry.Level < LogLevel.Important || entry.Target > LoggingTarget.Database || entry.Target == null) return;
if (entry.Exception is SentryOnlyDiagnosticsException)
return;
const int short_term_display_limit = 3;
if (recentLogCount < short_term_display_limit)
Schedule(() => Notifications.Post(new SimpleErrorNotification
{
Schedule(() => Notifications.Post(new SimpleErrorNotification
{
Icon = entry.Level == LogLevel.Important ? FontAwesome.Solid.ExclamationCircle : FontAwesome.Solid.Bomb,
Text = entry.Message.Truncate(256) + (entry.Exception != null && IsDeployedBuild ? "\n\nThis error has been automatically reported to the devs." : string.Empty),
}));
}
else if (recentLogCount == short_term_display_limit)
Icon = entry.Level == LogLevel.Important ? FontAwesome.Solid.ExclamationCircle : FontAwesome.Solid.Bomb,
Text = entry.Message.Truncate(256) + (entry.Exception != null && IsDeployedBuild ? "\n\nThis error has been automatically reported to the devs." : string.Empty),
}));
}
else if (generalLogRecentCount == short_term_display_limit)
{
string logFile = Logger.GetLogger(entry.Target.Value).Filename;
Schedule(() => Notifications.Post(new SimpleNotification
{
string logFile = Logger.GetLogger(entry.Target.Value).Filename;
Schedule(() => Notifications.Post(new SimpleNotification
Icon = FontAwesome.Solid.EllipsisH,
Text = NotificationsStrings.SubsequentMessagesLogged,
Activated = () =>
{
Icon = FontAwesome.Solid.EllipsisH,
Text = NotificationsStrings.SubsequentMessagesLogged,
Activated = () =>
{
Logger.Storage.PresentFileExternally(logFile);
return true;
}
}));
}
Logger.Storage.PresentFileExternally(logFile);
return true;
}
}));
}
Interlocked.Increment(ref recentLogCount);
Scheduler.AddDelayed(() => Interlocked.Decrement(ref recentLogCount), debounce);
};
Interlocked.Increment(ref generalLogRecentCount);
Scheduler.AddDelayed(() => Interlocked.Decrement(ref generalLogRecentCount), general_log_debounce);
}
private void forwardTabletLogsToNotifications()
private void forwardTabletLogToNotifications(LogEntry entry)
{
const string tablet_prefix = @"[Tablet] ";
if (entry.Level < LogLevel.Important || entry.Target != LoggingTarget.Input || !entry.Message.StartsWith(tablet_log_prefix, StringComparison.OrdinalIgnoreCase))
return;
bool notifyOnWarning = true;
bool notifyOnError = true;
string message = entry.Message.Replace(tablet_log_prefix, string.Empty);
Logger.NewEntry += entry =>
if (entry.Level == LogLevel.Error)
{
if (entry.Level < LogLevel.Important || entry.Target != LoggingTarget.Input || !entry.Message.StartsWith(tablet_prefix, StringComparison.OrdinalIgnoreCase))
if (!tabletLogNotifyOnError)
return;
string message = entry.Message.Replace(tablet_prefix, string.Empty);
tabletLogNotifyOnError = false;
if (entry.Level == LogLevel.Error)
Schedule(() =>
{
if (!notifyOnError)
return;
notifyOnError = false;
Schedule(() =>
Notifications.Post(new SimpleNotification
{
Notifications.Post(new SimpleNotification
{
Text = NotificationsStrings.TabletSupportDisabledDueToError(message),
Icon = FontAwesome.Solid.PenSquare,
IconColour = Colours.RedDark,
});
// We only have one tablet handler currently.
// The loop here is weakly guarding against a future where more than one is added.
// If this is ever the case, this logic needs adjustment as it should probably only
// disable the relevant tablet handler rather than all.
foreach (var tabletHandler in Host.AvailableInputHandlers.OfType<ITabletHandler>())
tabletHandler.Enabled.Value = false;
});
}
else if (notifyOnWarning)
{
Schedule(() => Notifications.Post(new SimpleNotification
{
Text = NotificationsStrings.EncounteredTabletWarning,
Text = NotificationsStrings.TabletSupportDisabledDueToError(message),
Icon = FontAwesome.Solid.PenSquare,
IconColour = Colours.YellowDark,
Activated = () =>
{
OpenUrlExternally("https://opentabletdriver.net/Tablets", LinkWarnMode.NeverWarn);
return true;
}
}));
IconColour = Colours.RedDark,
});
notifyOnWarning = false;
}
};
Schedule(() =>
// We only have one tablet handler currently.
// The loop here is weakly guarding against a future where more than one is added.
// If this is ever the case, this logic needs adjustment as it should probably only
// disable the relevant tablet handler rather than all.
foreach (var tabletHandler in Host.AvailableInputHandlers.OfType<ITabletHandler>())
tabletHandler.Enabled.Value = false;
});
}
else if (tabletLogNotifyOnWarning)
{
ITabletHandler tablet = Host.AvailableInputHandlers.OfType<ITabletHandler>().SingleOrDefault();
tablet?.Tablet.BindValueChanged(_ =>
Schedule(() => Notifications.Post(new SimpleNotification
{
notifyOnWarning = true;
notifyOnError = true;
}, true);
});
Text = NotificationsStrings.EncounteredTabletWarning,
Icon = FontAwesome.Solid.PenSquare,
IconColour = Colours.YellowDark,
Activated = () =>
{
OpenUrlExternally("https://opentabletdriver.net/Tablets", LinkWarnMode.NeverWarn);
return true;
}
}));
tabletLogNotifyOnWarning = false;
}
}
private Task asyncLoadStream;