Fixed AddToGUIUpdateList crashes (I think):

The callbacks from the async requests to master server only assign the response to a variable, preventing GUIComponents from being manipulated from two threads simultaneously
This commit is contained in:
Regalis
2017-03-14 17:27:15 +02:00
parent 8c659e2a08
commit 3f590da395
2 changed files with 74 additions and 62 deletions
+53 -42
View File
@@ -35,6 +35,7 @@ namespace Barotrauma.Networking
private RestClient restClient; private RestClient restClient;
private bool masterServerResponded; private bool masterServerResponded;
private IRestResponse masterServerResponse;
private ServerLog log; private ServerLog log;
private GUIButton showLogButton; private GUIButton showLogButton;
@@ -222,7 +223,7 @@ namespace Barotrauma.Networking
if (isPublic) if (isPublic)
{ {
RegisterToMasterServer(); CoroutineManager.StartCoroutine(RegisterToMasterServer());
} }
updateInterval = new TimeSpan(0, 0, 0, 0, 150); updateInterval = new TimeSpan(0, 0, 0, 0, 150);
@@ -234,7 +235,7 @@ namespace Barotrauma.Networking
yield return CoroutineStatus.Success; yield return CoroutineStatus.Success;
} }
private void RegisterToMasterServer() private IEnumerable<object> RegisterToMasterServer()
{ {
if (restClient==null) if (restClient==null)
{ {
@@ -248,25 +249,40 @@ namespace Barotrauma.Networking
request.AddParameter("currplayers", connectedClients.Count); request.AddParameter("currplayers", connectedClients.Count);
request.AddParameter("maxplayers", MaxPlayers); request.AddParameter("maxplayers", MaxPlayers);
request.AddParameter("password", string.IsNullOrWhiteSpace(password) ? 0 : 1); request.AddParameter("password", string.IsNullOrWhiteSpace(password) ? 0 : 1);
// execute the request masterServerResponded = false;
restClient.ExecuteAsync(request, response => masterServerResponse = null;
var restRequestHandle = restClient.ExecuteAsync(request, response => MasterServerCallBack(response));
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 15);
while (!masterServerResponded)
{ {
if (response.StatusCode != System.Net.HttpStatusCode.OK) if (DateTime.Now > timeOut)
{ {
DebugConsole.ThrowError("Error while connecting to master server (" + response.StatusCode + ": " + response.StatusDescription + ")"); restRequestHandle.Abort();
return; DebugConsole.NewMessage("Couldn't register to master server (request timed out)", Color.Red);
Log("Couldn't register to master server (request timed out)", Color.Red);
yield return CoroutineStatus.Success;
} }
if (response != null && !string.IsNullOrWhiteSpace(response.Content)) yield return CoroutineStatus.Running;
{ }
DebugConsole.ThrowError("Error while connecting to master server (" + response.Content + ")");
return;
}
if (masterServerResponse.StatusCode != System.Net.HttpStatusCode.OK)
{
DebugConsole.ThrowError("Error while connecting to master server (" + masterServerResponse.StatusCode + ": " + masterServerResponse.StatusDescription + ")");
}
else if (masterServerResponse != null && !string.IsNullOrWhiteSpace(masterServerResponse.Content))
{
DebugConsole.ThrowError("Error while connecting to master server (" + masterServerResponse.Content + ")");
}
else
{
registeredToMaster = true; registeredToMaster = true;
refreshMasterTimer = DateTime.Now + refreshMasterInterval; refreshMasterTimer = DateTime.Now + refreshMasterInterval;
}); }
yield return CoroutineStatus.Success;
} }
private IEnumerable<object> RefreshMaster() private IEnumerable<object> RefreshMaster()
@@ -289,6 +305,7 @@ namespace Barotrauma.Networking
sw.Start(); sw.Start();
masterServerResponded = false; masterServerResponded = false;
masterServerResponse = null;
var restRequestHandle = restClient.ExecuteAsync(request, response => MasterServerCallBack(response)); var restRequestHandle = restClient.ExecuteAsync(request, response => MasterServerCallBack(response));
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 15); DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 15);
@@ -298,16 +315,33 @@ namespace Barotrauma.Networking
{ {
restRequestHandle.Abort(); restRequestHandle.Abort();
DebugConsole.NewMessage("Couldn't connect to master server (request timed out)", Color.Red); DebugConsole.NewMessage("Couldn't connect to master server (request timed out)", Color.Red);
Log("Couldn't connect to master server (request timed out)", Color.Red); Log("Couldn't connect to master server (request timed out)", Color.Red);
yield return CoroutineStatus.Success;
break;
//registeredToMaster = false;
} }
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
} }
if (masterServerResponse.Content == "Error: server not found")
{
Log("Not registered to master server, re-registering...", Color.Red);
CoroutineManager.StartCoroutine(RegisterToMasterServer());
}
else if (masterServerResponse.ErrorException != null)
{
DebugConsole.NewMessage("Error while registering to master server (" + masterServerResponse.ErrorException + ")", Color.Red);
Log("Error while registering to master server (" + masterServerResponse.ErrorException + ")", Color.Red);
}
else if (masterServerResponse.StatusCode != System.Net.HttpStatusCode.OK)
{
DebugConsole.NewMessage("Error while reporting to master server (" + masterServerResponse.StatusCode + ": " + masterServerResponse.StatusDescription + ")", Color.Red);
Log("Error while reporting to master server (" + masterServerResponse.StatusCode + ": " + masterServerResponse.StatusDescription + ")", Color.Red);
}
else
{
Log("Master server responded", Color.Cyan);
}
System.Diagnostics.Debug.WriteLine("took "+sw.ElapsedMilliseconds+" ms"); System.Diagnostics.Debug.WriteLine("took "+sw.ElapsedMilliseconds+" ms");
yield return CoroutineStatus.Success; yield return CoroutineStatus.Success;
@@ -315,31 +349,8 @@ namespace Barotrauma.Networking
private void MasterServerCallBack(IRestResponse response) private void MasterServerCallBack(IRestResponse response)
{ {
masterServerResponse = response;
masterServerResponded = true; masterServerResponded = true;
if (response.Content=="Error: server not found")
{
Log("Not registered to master server, re-registering...", Color.Red);
RegisterToMasterServer();
return;
}
if (response.ErrorException != null)
{
DebugConsole.NewMessage("Error while registering to master server (" + response.ErrorException + ")", Color.Red);
Log("Error while registering to master server (" + response.ErrorException + ")", Color.Red);
return;
}
if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
DebugConsole.NewMessage("Error while reporting to master server (" + response.StatusCode + ": " + response.StatusDescription + ")", Color.Red);
Log("Error while reporting to master server (" + response.StatusCode + ": " + response.StatusDescription + ")", Color.Red);
return;
}
Log("Master server responded", Color.Cyan);
} }
public override void AddToGUIUpdateList() public override void AddToGUIUpdateList()
+21 -20
View File
@@ -22,6 +22,7 @@ namespace Barotrauma
//private RestRequestAsyncHandle restRequestHandle; //private RestRequestAsyncHandle restRequestHandle;
private bool masterServerResponded; private bool masterServerResponded;
private IRestResponse masterServerResponse;
private int[] columnX; private int[] columnX;
@@ -229,30 +230,21 @@ namespace Barotrauma
serverList.ClearChildren(); serverList.ClearChildren();
restRequestHandle.Abort(); restRequestHandle.Abort();
DebugConsole.ThrowError("Couldn't connect to master server (request timed out)"); DebugConsole.ThrowError("Couldn't connect to master server (request timed out)");
yield return CoroutineStatus.Success;
} }
yield return CoroutineStatus.Running; yield return CoroutineStatus.Running;
} }
yield return CoroutineStatus.Success; if (masterServerResponse.ErrorException != null)
}
private void MasterServerCallBack(IRestResponse response)
{
masterServerResponded = true;
if (response.ErrorException!=null)
{ {
serverList.ClearChildren(); serverList.ClearChildren();
DebugConsole.ThrowError("Error while connecting to master server", response.ErrorException); DebugConsole.ThrowError("Error while connecting to master server", masterServerResponse.ErrorException);
return;
} }
else if (masterServerResponse.StatusCode != System.Net.HttpStatusCode.OK)
if (response.StatusCode!= System.Net.HttpStatusCode.OK)
{ {
serverList.ClearChildren(); serverList.ClearChildren();
switch (response.StatusCode) switch (masterServerResponse.StatusCode)
{ {
case System.Net.HttpStatusCode.NotFound: case System.Net.HttpStatusCode.NotFound:
DebugConsole.ThrowError("Error while connecting to master server (404 - \"" + NetConfig.MasterServerUrl + "\" not found)"); DebugConsole.ThrowError("Error while connecting to master server (404 - \"" + NetConfig.MasterServerUrl + "\" not found)");
@@ -262,14 +254,23 @@ namespace Barotrauma
DebugConsole.ThrowError("The master server may be down for maintenance or temporarily overloaded. Please try again after in a few moments."); DebugConsole.ThrowError("The master server may be down for maintenance or temporarily overloaded. Please try again after in a few moments.");
break; break;
default: default:
DebugConsole.ThrowError("Error while connecting to master server (" +response.StatusCode+": "+response.StatusDescription+")"); DebugConsole.ThrowError("Error while connecting to master server (" + masterServerResponse.StatusCode + ": " + masterServerResponse.StatusDescription + ")");
break; break;
} }
}
return; else
{
UpdateServerList(masterServerResponse.Content);
} }
UpdateServerList(response.Content); yield return CoroutineStatus.Success;
}
private void MasterServerCallBack(IRestResponse response)
{
masterServerResponse = response;
masterServerResponded = true;
} }
private bool JoinServer(GUIButton button, object obj) private bool JoinServer(GUIButton button, object obj)