diff --git a/TGS.Server/Instance/Instance.cs b/TGS.Server/Instance/Instance.cs
index e28d58dc72..a5663c1bed 100644
--- a/TGS.Server/Instance/Instance.cs
+++ b/TGS.Server/Instance/Instance.cs
@@ -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);
}
+ ///
+ /// Dumps the status of all locks in the
+ ///
+ 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);
+ }
+
///
public string Version()
{
diff --git a/TGS.Server/Instance/Interop.cs b/TGS.Server/Instance/Interop.cs
index 1cbe56e7fc..b56bc27251 100644
--- a/TGS.Server/Instance/Interop.cs
+++ b/TGS.Server/Instance/Interop.cs
@@ -65,6 +65,8 @@ namespace TGS.Server
List 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(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(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);
}
});
}