mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
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
This commit is contained in:
parent
e6ea29c914
commit
0f32771075
1 changed files with 45 additions and 20 deletions
|
|
@ -54,6 +54,8 @@ namespace MinecraftClient
|
||||||
private static Tuple<Thread, CancellationTokenSource>? offlinePrompt = null;
|
private static Tuple<Thread, CancellationTokenSource>? offlinePrompt = null;
|
||||||
private static IDisposable? _sentrySdk = null;
|
private static IDisposable? _sentrySdk = null;
|
||||||
private static bool useMcVersionOnce = false;
|
private static bool useMcVersionOnce = false;
|
||||||
|
private static Thread? _restartThread = null;
|
||||||
|
private static readonly object _restartLock = new();
|
||||||
private static string settingsIniPath = "MinecraftClient.ini";
|
private static string settingsIniPath = "MinecraftClient.ini";
|
||||||
|
|
||||||
// [SENTRY]
|
// [SENTRY]
|
||||||
|
|
@ -892,25 +894,45 @@ namespace MinecraftClient
|
||||||
/// <param name="keepAccountAndServerSettings">Optional, keep account and server settings</param>
|
/// <param name="keepAccountAndServerSettings">Optional, keep account and server settings</param>
|
||||||
public static void Restart(int delaySeconds = 0, bool keepAccountAndServerSettings = false)
|
public static void Restart(int delaySeconds = 0, bool keepAccountAndServerSettings = false)
|
||||||
{
|
{
|
||||||
ConsoleIO.Backend?.StopReadThread();
|
lock (_restartLock)
|
||||||
new Thread(new ThreadStart(delegate
|
|
||||||
{
|
{
|
||||||
if (client is not null) { client.Disconnect(); ConsoleIO.Reset(); }
|
if (_restartThread is not null && _restartThread.IsAlive
|
||||||
if (offlinePrompt is not null)
|
&& _restartThread != Thread.CurrentThread)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ConsoleIO.Backend?.StopReadThread();
|
||||||
|
var thread = new Thread(new ThreadStart(delegate
|
||||||
{
|
{
|
||||||
if (ConsoleIO.Backend is not null)
|
try
|
||||||
ConsoleIO.Backend.OnInputChange -= ConsoleIO.OfflineAutocompleteHandler;
|
{
|
||||||
offlinePrompt.Item2.Cancel(); offlinePrompt.Item1.Join(); offlinePrompt = null; ConsoleIO.Reset();
|
if (client is not null) { client.Disconnect(); ConsoleIO.Reset(); }
|
||||||
}
|
if (offlinePrompt is not null)
|
||||||
if (delaySeconds > 0)
|
{
|
||||||
{
|
if (ConsoleIO.Backend is not null)
|
||||||
ConsoleIO.WriteLine(string.Format(Translations.mcc_restart_delay, delaySeconds));
|
ConsoleIO.Backend.OnInputChange -= ConsoleIO.OfflineAutocompleteHandler;
|
||||||
Thread.Sleep(delaySeconds * 1000);
|
offlinePrompt.Item2.Cancel(); offlinePrompt.Item1.Join(); offlinePrompt = null; ConsoleIO.Reset();
|
||||||
}
|
}
|
||||||
ConsoleIO.WriteLine(Translations.mcc_restart);
|
if (delaySeconds > 0)
|
||||||
ReloadSettings(keepAccountAndServerSettings);
|
{
|
||||||
InitializeClient();
|
ConsoleIO.WriteLine(string.Format(Translations.mcc_restart_delay, delaySeconds));
|
||||||
})).Start();
|
Thread.Sleep(delaySeconds * 1000);
|
||||||
|
}
|
||||||
|
ConsoleIO.WriteLine(Translations.mcc_restart);
|
||||||
|
ReloadSettings(keepAccountAndServerSettings);
|
||||||
|
InitializeClient();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
lock (_restartLock)
|
||||||
|
{
|
||||||
|
if (_restartThread == Thread.CurrentThread)
|
||||||
|
_restartThread = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
_restartThread = thread;
|
||||||
|
thread.Start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void DoExit(int exitcode = 0)
|
public static void DoExit(int exitcode = 0)
|
||||||
|
|
@ -951,6 +973,8 @@ namespace MinecraftClient
|
||||||
/// <param name="disconnectReason">If set, the error message will be processed by the AutoRelog bot</param>
|
/// <param name="disconnectReason">If set, the error message will be processed by the AutoRelog bot</param>
|
||||||
public static void HandleFailure(string? errorMessage = null, bool versionError = false, ChatBot.DisconnectReason? disconnectReason = null)
|
public static void HandleFailure(string? errorMessage = null, bool versionError = false, ChatBot.DisconnectReason? disconnectReason = null)
|
||||||
{
|
{
|
||||||
|
bool autoRelogHandled = false;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(errorMessage))
|
if (!string.IsNullOrEmpty(errorMessage))
|
||||||
{
|
{
|
||||||
ConsoleIO.Reset();
|
ConsoleIO.Reset();
|
||||||
|
|
@ -967,8 +991,9 @@ namespace MinecraftClient
|
||||||
|
|
||||||
if (disconnectReason.HasValue)
|
if (disconnectReason.HasValue)
|
||||||
{
|
{
|
||||||
|
autoRelogHandled = true;
|
||||||
if (ChatBots.AutoRelog.OnDisconnectStatic(disconnectReason.Value, errorMessage))
|
if (ChatBots.AutoRelog.OnDisconnectStatic(disconnectReason.Value, errorMessage))
|
||||||
return; //AutoRelog is triggering a restart of the client
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -986,10 +1011,10 @@ namespace MinecraftClient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disconnectReason.HasValue)
|
if (!autoRelogHandled && disconnectReason.HasValue)
|
||||||
{
|
{
|
||||||
if (ChatBots.AutoRelog.OnDisconnectStatic(disconnectReason.Value, errorMessage!))
|
if (ChatBots.AutoRelog.OnDisconnectStatic(disconnectReason.Value, errorMessage!))
|
||||||
return; //AutoRelog is triggering a restart of the client, don't turn on the offline prompt
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offlinePrompt is null)
|
if (offlinePrompt is null)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue