Fixes exiting/crash handling/ctrl+c (#237)

- [X] Fixes handling of CTRL+C
- [X] Fixes crash guard (but should really be rewritten
- [X] Fixes exiting/restarting

Bumps release version
This commit is contained in:
Kamron Batman 2020-09-12 00:05:38 -07:00 • committed by GitHub
parent 76a9729f61
commit 55ae0f8778
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 216 additions and 160 deletions

View file

@ -1,22 +1,17 @@
/***************************************************************************
* Main.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Main.cs *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Collections.Generic;
@ -42,7 +37,6 @@ namespace Server
private static bool m_Crashed;
private static Thread timerThread;
private static string m_BaseDirectory;
private static string m_ExePath;
private static bool m_Profiling;
private static DateTime m_ProfileStart;
@ -62,8 +56,6 @@ namespace Server
private static readonly double m_HighFrequency = 1000.0 / Stopwatch.Frequency;
private static readonly double m_LowFrequency = 1000.0 / TimeSpan.TicksPerSecond;
internal static ConsoleEventHandler m_ConsoleEventHandler;
private static int m_CycleIndex = 1;
private static readonly float[] m_CyclesPerSecond = new float[100];
@ -138,8 +130,6 @@ namespace Server
public static int ProcessorCount { get; private set; }
public static string ExePath => m_ExePath ??= Assembly.Location;
public static string BaseDirectory
{
get
@ -148,7 +138,7 @@ namespace Server
{
try
{
m_BaseDirectory = ExePath;
m_BaseDirectory = Assembly.Location;
if (m_BaseDirectory.Length > 0)
{
@ -165,7 +155,9 @@ namespace Server
}
}
public static bool Closing { get; private set; }
public static CancellationTokenSource ClosingTokenSource { get; } = new CancellationTokenSource();
public static bool Closing => ClosingTokenSource.IsCancellationRequested;
public static float CyclesPerSecond => m_CyclesPerSecond[(m_CycleIndex - 1) % m_CyclesPerSecond.Length];
@ -279,15 +271,6 @@ namespace Server
if (!close)
{
try
{
// Close all listeners
}
catch
{
// ignored
}
Console.WriteLine("This exception is fatal, press return to exit");
Console.ReadLine();
}
@ -296,30 +279,56 @@ namespace Server
}
}
private static bool OnConsoleEvent(ConsoleEventType type)
{
if (World.Saving || type == ConsoleEventType.CTRL_LOGOFF_EVENT)
{
return true;
}
Kill(); // Kill -> HandleClosed will handle waiting for the completion of flushing to disk
return true;
}
private static void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
HandleClosed();
if (!Closing)
{
HandleClosed();
}
}
private static void Console_CancelKeyPressed(object sender, ConsoleCancelEventArgs e)
{
var keypress = e.SpecialKey switch
{
ConsoleSpecialKey.ControlBreak => "CTRL+BREAK",
_ => "CTRL+C"
};
Console.WriteLine("Core: Detected {0} pressed.", keypress);
e.Cancel = true;
Kill();
}
public static void Kill(bool restart = false)
{
if (Closing)
{
return;
}
HandleClosed();
if (restart)
{
Process.Start(ExePath, Arguments);
if (IsWindows)
{
Process.Start("dotnet", Assembly.Location);
}
else
{
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = Assembly.Location,
UseShellExecute = true
}
};
process.Start();
}
}
Process.Kill();
@ -327,14 +336,9 @@ namespace Server
private static void HandleClosed()
{
if (Closing)
{
return;
}
ClosingTokenSource.Cancel();
Closing = true;
Console.Write("Exiting...");
Console.Write("Core: Shutting down...");
World.WaitForWriteCompletion();
@ -426,11 +430,7 @@ namespace Server
Console.WriteLine("Core: Optimizing for {0} processor{1}", ProcessorCount, ProcessorCount == 1 ? "" : "s");
}
if (IsWindows)
{
m_ConsoleEventHandler = OnConsoleEvent;
UnsafeNativeMethods.SetConsoleCtrlHandler(m_ConsoleEventHandler, true);
}
Console.CancelKeyPress += Console_CancelKeyPressed;
if (GCSettings.IsServerGC)
{
@ -472,13 +472,14 @@ namespace Server
EventSink.InvokeServerStarted();
// Start net socket server
var host = TcpServer.CreateWebHostBuilder().Build();
var life = host.Services.GetRequiredService<IHostApplicationLifetime>();
life.ApplicationStopping.Register(() => { Kill(); });
_tcpHost = TcpServer.CreateWebHostBuilder().Build();
host.Run();
// Run indefinitely and block
_tcpHost.RunAsync(ClosingTokenSource.Token).Wait();
}
private static IWebHost _tcpHost;
public static void RunEventLoop(IMessagePumpService messagePumpService)
{
try
@ -542,7 +543,10 @@ namespace Server
{
var isItem = type.IsSubclassOf(typeof(Item));
if (!isItem && !type.IsSubclassOf(typeof(Mobile))) return;
if (!isItem && !type.IsSubclassOf(typeof(Mobile)))
{
return;
}
if (isItem)
{
@ -595,22 +599,5 @@ namespace Server
Parallel.ForEach(assembly.GetTypes(), VerifyType);
}
}
internal enum ConsoleEventType
{
CTRL_C_EVENT,
CTRL_BREAK_EVENT,
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
}
internal delegate bool ConsoleEventHandler(ConsoleEventType type);
internal static class UnsafeNativeMethods
{
[DllImport("Kernel32")]
internal static extern bool SetConsoleCtrlHandler(ConsoleEventHandler callback, bool add);
}
}
}