1
0
mirror of https://github.com/ppy/osu.git synced 2025-03-10 21:40:34 +08:00

Merge pull request #32214 from smoogipoo/fix-multi-user-kick-threading

Fix thread safety when kicking multiplayer users
This commit is contained in:
Bartłomiej Dach 2025-03-04 09:24:08 +01:00 committed by GitHub
commit 28be0e31c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 34 deletions

View File

@ -487,18 +487,44 @@ namespace osu.Game.Online.Multiplayer
}, false); }, false);
} }
Task IMultiplayerClient.UserLeft(MultiplayerRoomUser user) => Task IMultiplayerClient.UserLeft(MultiplayerRoomUser user)
handleUserLeft(user, UserLeft); {
Scheduler.Add(() => handleUserLeft(user, UserLeft), false);
return Task.CompletedTask;
}
Task IMultiplayerClient.UserKicked(MultiplayerRoomUser user) Task IMultiplayerClient.UserKicked(MultiplayerRoomUser user)
{ {
if (LocalUser == null) Scheduler.Add(() =>
return Task.CompletedTask; {
if (LocalUser == null)
return;
if (user.Equals(LocalUser)) if (user.Equals(LocalUser))
LeaveRoom(); LeaveRoom();
return handleUserLeft(user, UserKicked); handleUserLeft(user, UserKicked);
}, false);
return Task.CompletedTask;
}
private void handleUserLeft(MultiplayerRoomUser user, Action<MultiplayerRoomUser>? callback)
{
Debug.Assert(ThreadSafety.IsUpdateThread);
if (Room == null)
return;
Room.Users.Remove(user);
PlayingUserIds.Remove(user.UserID);
Debug.Assert(APIRoom != null);
APIRoom.RecentParticipants = APIRoom.RecentParticipants.Where(u => u.Id != user.UserID).ToArray();
APIRoom.ParticipantCount--;
callback?.Invoke(user);
RoomUpdated?.Invoke();
} }
async Task IMultiplayerClient.Invited(int invitedBy, long roomID, string password) async Task IMultiplayerClient.Invited(int invitedBy, long roomID, string password)
@ -545,27 +571,6 @@ namespace osu.Game.Online.Multiplayer
APIRoom.ParticipantCount++; APIRoom.ParticipantCount++;
} }
private Task handleUserLeft(MultiplayerRoomUser user, Action<MultiplayerRoomUser>? callback)
{
Scheduler.Add(() =>
{
if (Room == null)
return;
Room.Users.Remove(user);
PlayingUserIds.Remove(user.UserID);
Debug.Assert(APIRoom != null);
APIRoom.RecentParticipants = APIRoom.RecentParticipants.Where(u => u.Id != user.UserID).ToArray();
APIRoom.ParticipantCount--;
callback?.Invoke(user);
RoomUpdated?.Invoke();
}, false);
return Task.CompletedTask;
}
Task IMultiplayerClient.HostChanged(int userId) Task IMultiplayerClient.HostChanged(int userId)
{ {
Scheduler.Add(() => Scheduler.Add(() =>

View File

@ -28,11 +28,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
private void onRoomUpdated() private void onRoomUpdated()
{ {
if (client.Room == null) if (client.Room == null || client.LocalUser == null)
return; return;
Debug.Assert(client.LocalUser != null);
// If the user exits gameplay before score submission completes, we'll transition to idle when results has been prepared. // If the user exits gameplay before score submission completes, we'll transition to idle when results has been prepared.
if (client.LocalUser.State == MultiplayerUserState.Results && this.IsCurrentScreen()) if (client.LocalUser.State == MultiplayerUserState.Results && this.IsCurrentScreen())
transitionFromResults(); transitionFromResults();
@ -62,11 +60,9 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
{ {
base.OnResuming(e); base.OnResuming(e);
if (client.Room == null) if (client.Room == null || client.LocalUser == null)
return; return;
Debug.Assert(client.LocalUser != null);
if (!(e.Last is MultiplayerPlayerLoader playerLoader)) if (!(e.Last is MultiplayerPlayerLoader playerLoader))
return; return;