mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 21:07:33 +08:00
Merge pull request #11266 from peppy/fix-hard-crash-on-signal-r-exceptions
This commit is contained in:
commit
3087aba5bc
26
osu.Game/Extensions/TaskExtensions.cs
Normal file
26
osu.Game/Extensions/TaskExtensions.cs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using osu.Framework.Logging;
|
||||
|
||||
namespace osu.Game.Extensions
|
||||
{
|
||||
public static class TaskExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Denote a task which is to be run without local error handling logic, where failure is not catastrophic.
|
||||
/// Avoids unobserved exceptions from being fired.
|
||||
/// </summary>
|
||||
/// <param name="task">The task.</param>
|
||||
/// <param name="logOnError">Whether errors should be logged as important, or silently ignored.</param>
|
||||
public static void CatchUnobservedExceptions(this Task task, bool logOnError = false)
|
||||
{
|
||||
task.ContinueWith(t =>
|
||||
{
|
||||
if (logOnError)
|
||||
Logger.Log($"Error running task: {t.Exception?.Message ?? "unknown"}", LoggingTarget.Runtime, LogLevel.Important);
|
||||
}, TaskContinuationOptions.NotOnRanToCompletion);
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Database;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
@ -84,7 +85,7 @@ namespace osu.Game.Online.RealtimeMultiplayer
|
||||
if (!connected.NewValue)
|
||||
{
|
||||
Logger.Log("Connection to multiplayer server was lost.", LoggingTarget.Runtime, LogLevel.Important);
|
||||
LeaveRoom();
|
||||
LeaveRoom().CatchUnobservedExceptions();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using JetBrains.Annotations;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Backgrounds;
|
||||
using osu.Game.Online.API;
|
||||
@ -105,13 +106,13 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer.Match
|
||||
return;
|
||||
|
||||
if (localUser.State == MultiplayerUserState.Idle)
|
||||
Client.ChangeState(MultiplayerUserState.Ready);
|
||||
Client.ChangeState(MultiplayerUserState.Ready).CatchUnobservedExceptions(true);
|
||||
else
|
||||
{
|
||||
if (Room?.Host?.Equals(localUser) == true)
|
||||
Client.StartMatch();
|
||||
Client.StartMatch().CatchUnobservedExceptions(true);
|
||||
else
|
||||
Client.ChangeState(MultiplayerUserState.Idle);
|
||||
Client.ChangeState(MultiplayerUserState.Idle).CatchUnobservedExceptions(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ using osu.Framework.Graphics.Cursor;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
@ -176,7 +177,7 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer.Participants
|
||||
if (Room.Host?.UserID != api.LocalUser.Value.Id)
|
||||
return;
|
||||
|
||||
Client.TransferHost(targetUser);
|
||||
Client.TransferHost(targetUser).CatchUnobservedExceptions(true);
|
||||
})
|
||||
};
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer
|
||||
|
||||
client.ChangeSettings(item: item).ContinueWith(t =>
|
||||
{
|
||||
return Schedule(() =>
|
||||
Schedule(() =>
|
||||
{
|
||||
loadingLayer.Hide();
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.RealtimeMultiplayer;
|
||||
using osu.Game.Screens.Multi.Components;
|
||||
@ -21,7 +22,7 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer
|
||||
base.OnResuming(last);
|
||||
|
||||
if (client.Room != null)
|
||||
client.ChangeState(MultiplayerUserState.Idle);
|
||||
client.ChangeState(MultiplayerUserState.Idle).CatchUnobservedExceptions(true);
|
||||
}
|
||||
|
||||
protected override void UpdatePollingRate(bool isIdle)
|
||||
|
@ -58,20 +58,18 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer
|
||||
{
|
||||
if (!connected.NewValue)
|
||||
{
|
||||
startedEvent.Set();
|
||||
|
||||
// messaging to the user about this disconnect will be provided by the RealtimeMatchSubScreen.
|
||||
Schedule(() => PerformExit(false));
|
||||
failAndBail();
|
||||
}
|
||||
}, true);
|
||||
|
||||
client.ChangeState(MultiplayerUserState.Loaded);
|
||||
client.ChangeState(MultiplayerUserState.Loaded)
|
||||
.ContinueWith(task => failAndBail(task.Exception?.Message ?? "Server error"), TaskContinuationOptions.NotOnRanToCompletion);
|
||||
|
||||
if (!startedEvent.Wait(TimeSpan.FromSeconds(30)))
|
||||
{
|
||||
Logger.Log("Failed to start the multiplayer match in time.", LoggingTarget.Runtime, LogLevel.Important);
|
||||
|
||||
Schedule(() => PerformExit(false));
|
||||
failAndBail("Failed to start the multiplayer match in time.");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Assert(client.Room != null);
|
||||
@ -82,6 +80,15 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer
|
||||
LoadComponentAsync(leaderboard = new MultiplayerGameplayLeaderboard(ScoreProcessor, userIds), HUDOverlay.Add);
|
||||
}
|
||||
|
||||
private void failAndBail(string message = null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(message))
|
||||
Logger.Log(message, LoggingTarget.Runtime, LogLevel.Important);
|
||||
|
||||
startedEvent.Set();
|
||||
Schedule(() => PerformExit(false));
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
@ -8,6 +8,7 @@ using System.Threading.Tasks;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Extensions;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Multiplayer.RoomStatuses;
|
||||
using osu.Game.Online.RealtimeMultiplayer;
|
||||
@ -68,7 +69,8 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer
|
||||
var joinedRoom = JoinedRoom.Value;
|
||||
|
||||
base.PartRoom();
|
||||
multiplayerClient.LeaveRoom();
|
||||
|
||||
multiplayerClient.LeaveRoom().CatchUnobservedExceptions();
|
||||
|
||||
// Todo: This is not the way to do this. Basically when we're the only participant and the room closes, there's no way to know if this is actually the case.
|
||||
// This is delayed one frame because upon exiting the match subscreen, multiplayer updates the polling rate and messes with polling.
|
||||
@ -83,15 +85,19 @@ namespace osu.Game.Screens.Multi.RealtimeMultiplayer
|
||||
{
|
||||
Debug.Assert(room.RoomID.Value != null);
|
||||
|
||||
var joinTask = multiplayerClient.JoinRoom(room);
|
||||
joinTask.ContinueWith(_ => Schedule(() => onSuccess?.Invoke(room)), TaskContinuationOptions.OnlyOnRanToCompletion);
|
||||
joinTask.ContinueWith(t =>
|
||||
multiplayerClient.JoinRoom(room).ContinueWith(t =>
|
||||
{
|
||||
PartRoom();
|
||||
if (t.Exception != null)
|
||||
Logger.Error(t.Exception, "Failed to join multiplayer room.");
|
||||
Schedule(() => onError?.Invoke(t.Exception?.ToString() ?? string.Empty));
|
||||
}, TaskContinuationOptions.NotOnRanToCompletion);
|
||||
if (t.IsCompletedSuccessfully)
|
||||
Schedule(() => onSuccess?.Invoke(room));
|
||||
else
|
||||
{
|
||||
if (t.Exception != null)
|
||||
Logger.Error(t.Exception, "Failed to join multiplayer room.");
|
||||
|
||||
PartRoom();
|
||||
Schedule(() => onError?.Invoke(t.Exception?.ToString() ?? string.Empty));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updatePolling()
|
||||
|
Loading…
Reference in New Issue
Block a user