mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-08-29 08:00:19 +01:00
If handle command is called again before the previous invocation finishes it dumps lock statuses
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.ServiceModel;
|
||||
using System.Threading;
|
||||
using TGS.Interface.Components;
|
||||
|
||||
namespace TGS.Server
|
||||
@@ -104,6 +104,23 @@ namespace TGS.Server
|
||||
return Path.Combine(Config.Directory, path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dumps the status of all locks in the <see cref="Instance"/>
|
||||
/// </summary>
|
||||
public void DumpLocks()
|
||||
{
|
||||
var res = Monitor.TryEnter(RepoLock);
|
||||
string rb;
|
||||
if (res)
|
||||
{
|
||||
rb = RepoBusy.ToString();
|
||||
Monitor.Exit(RepoLock);
|
||||
}
|
||||
else
|
||||
rb = "UNKNOWN";
|
||||
Server.Logger.WriteWarning(String.Format("Started HandleCommand with others running! Active locks: Repo: {0}, Byond: {1}, Compiler: {2}, Topic: {3}, Config: {4}, Watchdog: {5}, Chat: {6}, this: {7}, restartLock: {8}, autoUpdateLock: {9}, RepoBusy: {10}", !res, CheckLocked(ByondLock), CheckLocked(CompilerLock), CheckLocked(topicLock), CheckLocked(configLock), CheckLocked(watchdogLock), CheckLocked(ChatLock), CheckLocked(this), CheckLocked(restartLock), CheckLocked(autoUpdateTimer), rb), EventID.CallTracking, LoggingID);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Version()
|
||||
{
|
||||
|
||||
@@ -65,6 +65,8 @@ namespace TGS.Server
|
||||
|
||||
List<Command> ServerChatCommands;
|
||||
|
||||
int RunningCommandHandlers = 0;
|
||||
|
||||
void LoadServerChatCommands()
|
||||
{
|
||||
if (DaemonStatus() != DreamDaemonStatus.Online)
|
||||
@@ -88,72 +90,89 @@ namespace TGS.Server
|
||||
catch { }
|
||||
}
|
||||
|
||||
static bool CheckLocked(object o)
|
||||
{
|
||||
var res = Monitor.TryEnter(o);
|
||||
if (res)
|
||||
Monitor.Exit(o);
|
||||
return !res;
|
||||
}
|
||||
|
||||
//raw command string sent here via world.ExportService
|
||||
Task HandleCommand(string cmd)
|
||||
{
|
||||
return Task.Run(() =>
|
||||
{
|
||||
var splits = new List<string>(cmd.Split(' '));
|
||||
cmd = splits[0];
|
||||
splits.RemoveAt(0);
|
||||
|
||||
bool APIValid;
|
||||
lock (topicLock)
|
||||
if (Interlocked.Increment(ref RunningCommandHandlers) > 1)
|
||||
DumpLocks();
|
||||
try
|
||||
{
|
||||
APIValid = CheckAPIVersionConstraints();
|
||||
}
|
||||
var splits = new List<string>(cmd.Split(' '));
|
||||
cmd = splits[0];
|
||||
splits.RemoveAt(0);
|
||||
|
||||
if (!APIValid && cmd != SRAPIVersion)
|
||||
return; //SPEAK THE LANGUAGE!!!
|
||||
bool APIValid;
|
||||
lock (topicLock)
|
||||
{
|
||||
APIValid = CheckAPIVersionConstraints();
|
||||
}
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case SRIRCBroadcast:
|
||||
SendMessage("GAME: " + String.Join(" ", splits), MessageType.GameInfo);
|
||||
break;
|
||||
case SRKillProcess:
|
||||
KillMe();
|
||||
break;
|
||||
case SRIRCAdminChannelMessage:
|
||||
SendMessage("RELAY: " + String.Join(" ", splits), MessageType.AdminInfo);
|
||||
break;
|
||||
case SRWorldReboot:
|
||||
WriteInfo("World Rebooted", EventID.WorldReboot);
|
||||
WriteCurrentDDLog("World rebooted");
|
||||
ServerChatCommands = null;
|
||||
ChatConnectivityCheck();
|
||||
lock (CompilerLock)
|
||||
{
|
||||
if (UpdateStaged)
|
||||
if (!APIValid && cmd != SRAPIVersion)
|
||||
return; //SPEAK THE LANGUAGE!!!
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case SRIRCBroadcast:
|
||||
SendMessage("GAME: " + String.Join(" ", splits), MessageType.GameInfo);
|
||||
break;
|
||||
case SRKillProcess:
|
||||
KillMe();
|
||||
break;
|
||||
case SRIRCAdminChannelMessage:
|
||||
SendMessage("RELAY: " + String.Join(" ", splits), MessageType.AdminInfo);
|
||||
break;
|
||||
case SRWorldReboot:
|
||||
WriteInfo("World Rebooted", EventID.WorldReboot);
|
||||
WriteCurrentDDLog("World rebooted");
|
||||
ServerChatCommands = null;
|
||||
ChatConnectivityCheck();
|
||||
lock (CompilerLock)
|
||||
{
|
||||
UpdateStaged = false;
|
||||
lock (topicLock)
|
||||
if (UpdateStaged)
|
||||
{
|
||||
GameAPIVersion = null; //needs updating
|
||||
UpdateStaged = false;
|
||||
lock (topicLock)
|
||||
{
|
||||
GameAPIVersion = null; //needs updating
|
||||
}
|
||||
WriteInfo("Staged update applied", EventID.ServerUpdateApplied);
|
||||
}
|
||||
WriteInfo("Staged update applied", EventID.ServerUpdateApplied);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SRAPIVersion:
|
||||
lock (topicLock)
|
||||
{
|
||||
try
|
||||
break;
|
||||
case SRAPIVersion:
|
||||
lock (topicLock)
|
||||
{
|
||||
GameAPIVersion = new Version(splits[0]);
|
||||
if (!CheckAPIVersionConstraints())
|
||||
throw new Exception();
|
||||
try
|
||||
{
|
||||
GameAPIVersion = new Version(splits[0]);
|
||||
if (!CheckAPIVersionConstraints())
|
||||
throw new Exception();
|
||||
}
|
||||
catch
|
||||
{
|
||||
WriteWarning(String.Format("API version of the game ({0}) is incompatible with the current supported API versions (3.{2}.x.x). Interop disabled.", splits.Count > 1 ? splits[1] : "NULL", AllowedMajorAPIVersion), EventID.APIVersionMismatch);
|
||||
GameAPIVersion = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
WriteWarning(String.Format("API version of the game ({0}) is incompatible with the current supported API versions (3.{2}.x.x). Interop disabled.", splits.Count > 1 ? splits[1] : "NULL", AllowedMajorAPIVersion), EventID.APIVersionMismatch);
|
||||
GameAPIVersion = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//This needs to be done asyncronously otherwise DD won't be able to process it, because it's waiting for THIS THREAD to return
|
||||
ThreadPool.QueueUserWorkItem(_ => SendCommand(SCAPICompat));
|
||||
break;
|
||||
//This needs to be done asyncronously otherwise DD won't be able to process it, because it's waiting for THIS THREAD to return
|
||||
ThreadPool.QueueUserWorkItem(_ => SendCommand(SCAPICompat));
|
||||
break;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Decrement(ref RunningCommandHandlers);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user