Skip to content

Commit 0f32771

Browse files
committed
fix: prevent concurrent restart flood on rapid /reco (#3046)
- Add reentrant guard to Program.Restart: track the active restart thread and silently drop concurrent calls from other threads while allowing the restart thread itself to chain a new restart (needed for AutoRelog retry flow). - Fix double AutoRelog.OnDisconnectStatic invocation in HandleFailure: the method was called once in the error-message branch and again in the interactive-mode branch for the same failure event, doubling the retry counter increment and potentially spawning duplicate restarts. Made-with: Cursor
1 parent e6ea29c commit 0f32771

1 file changed

Lines changed: 45 additions & 20 deletions

File tree

MinecraftClient/Program.cs

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ static class Program
5454
private static Tuple<Thread, CancellationTokenSource>? offlinePrompt = null;
5555
private static IDisposable? _sentrySdk = null;
5656
private static bool useMcVersionOnce = false;
57+
private static Thread? _restartThread = null;
58+
private static readonly object _restartLock = new();
5759
private static string settingsIniPath = "MinecraftClient.ini";
5860

5961
// [SENTRY]
@@ -892,25 +894,45 @@ public static void WriteBackSettings(bool enableBackup = true)
892894
/// <param name="keepAccountAndServerSettings">Optional, keep account and server settings</param>
893895
public static void Restart(int delaySeconds = 0, bool keepAccountAndServerSettings = false)
894896
{
895-
ConsoleIO.Backend?.StopReadThread();
896-
new Thread(new ThreadStart(delegate
897+
lock (_restartLock)
897898
{
898-
if (client is not null) { client.Disconnect(); ConsoleIO.Reset(); }
899-
if (offlinePrompt is not null)
900-
{
901-
if (ConsoleIO.Backend is not null)
902-
ConsoleIO.Backend.OnInputChange -= ConsoleIO.OfflineAutocompleteHandler;
903-
offlinePrompt.Item2.Cancel(); offlinePrompt.Item1.Join(); offlinePrompt = null; ConsoleIO.Reset();
904-
}
905-
if (delaySeconds > 0)
899+
if (_restartThread is not null && _restartThread.IsAlive
900+
&& _restartThread != Thread.CurrentThread)
901+
return;
902+
903+
ConsoleIO.Backend?.StopReadThread();
904+
var thread = new Thread(new ThreadStart(delegate
906905
{
907-
ConsoleIO.WriteLine(string.Format(Translations.mcc_restart_delay, delaySeconds));
908-
Thread.Sleep(delaySeconds * 1000);
909-
}
910-
ConsoleIO.WriteLine(Translations.mcc_restart);
911-
ReloadSettings(keepAccountAndServerSettings);
912-
InitializeClient();
913-
})).Start();
906+
try
907+
{
908+
if (client is not null) { client.Disconnect(); ConsoleIO.Reset(); }
909+
if (offlinePrompt is not null)
910+
{
911+
if (ConsoleIO.Backend is not null)
912+
ConsoleIO.Backend.OnInputChange -= ConsoleIO.OfflineAutocompleteHandler;
913+
offlinePrompt.Item2.Cancel(); offlinePrompt.Item1.Join(); offlinePrompt = null; ConsoleIO.Reset();
914+
}
915+
if (delaySeconds > 0)
916+
{
917+
ConsoleIO.WriteLine(string.Format(Translations.mcc_restart_delay, delaySeconds));
918+
Thread.Sleep(delaySeconds * 1000);
919+
}
920+
ConsoleIO.WriteLine(Translations.mcc_restart);
921+
ReloadSettings(keepAccountAndServerSettings);
922+
InitializeClient();
923+
}
924+
finally
925+
{
926+
lock (_restartLock)
927+
{
928+
if (_restartThread == Thread.CurrentThread)
929+
_restartThread = null;
930+
}
931+
}
932+
}));
933+
_restartThread = thread;
934+
thread.Start();
935+
}
914936
}
915937

916938
public static void DoExit(int exitcode = 0)
@@ -951,6 +973,8 @@ public static void Exit(int exitcode = 0)
951973
/// <param name="disconnectReason">If set, the error message will be processed by the AutoRelog bot</param>
952974
public static void HandleFailure(string? errorMessage = null, bool versionError = false, ChatBot.DisconnectReason? disconnectReason = null)
953975
{
976+
bool autoRelogHandled = false;
977+
954978
if (!string.IsNullOrEmpty(errorMessage))
955979
{
956980
ConsoleIO.Reset();
@@ -967,8 +991,9 @@ public static void HandleFailure(string? errorMessage = null, bool versionError
967991

968992
if (disconnectReason.HasValue)
969993
{
994+
autoRelogHandled = true;
970995
if (ChatBots.AutoRelog.OnDisconnectStatic(disconnectReason.Value, errorMessage))
971-
return; //AutoRelog is triggering a restart of the client
996+
return;
972997
}
973998
}
974999

@@ -986,10 +1011,10 @@ public static void HandleFailure(string? errorMessage = null, bool versionError
9861011
}
9871012
}
9881013

989-
if (disconnectReason.HasValue)
1014+
if (!autoRelogHandled && disconnectReason.HasValue)
9901015
{
9911016
if (ChatBots.AutoRelog.OnDisconnectStatic(disconnectReason.Value, errorMessage!))
992-
return; //AutoRelog is triggering a restart of the client, don't turn on the offline prompt
1017+
return;
9931018
}
9941019

9951020
if (offlinePrompt is null)

0 commit comments

Comments
 (0)