XNA - Getting random crash

Monkey Forums/Monkey Bug Reports/XNA - Getting random crash

Rushino(Posted 2013) [#1]
Hello,

Dunno what happened but i am getting random crash exclusivly on XNA.

Here the details...

Temps ‚coul‚ 00:00:00.93
Exception non gérée : System.ArgumentOutOfRangeException: L'index était hors limites. Il ne doit pas être négatif et doit être inférieur à la taille de la collection.
Nom du paramètre : index
   à System.ThrowHelper.ThrowArgumentOutOfRangeException()
   à System.Collections.Generic.List`1.get_Item(Int32 index)
   à bb_std_lang.popErr() dans e:\Projets\Jeux\Skirmish Commanders\Sources\MonkeyClient\skirmishclient.build\xna\MonkeyGame\MonkeyGame\Program.cs:ligne 153
   à bb_tokeniser_JSONTokeniser.m_NextChar() dans e:\Projets\Jeux\Skirmish Commanders\Sources\MonkeyClient\skirmishclient.build\xna\MonkeyGame\MonkeyGame\Program.cs:ligne 8026
   à bb_tokeniser_JSONTokeniser.g_JSONTokeniser_new(String t_jsonString, Boolean t_silent) dans e:\Projets\Jeux\Skirmish Commanders\Sources\MonkeyClient\skirmishclient.build\xna\MonkeyGame\MonkeyGame\Program.cs:ligne 8036
   à bb_jsondata_JSONData.g_ReadJSON(String t_jsonString) dans e:\Projets\Jeux\Skirmish Commanders\Sources\MonkeyClient\skirmishclient.build\xna\MonkeyGame\MonkeyGame\Program.cs:ligne 3515
   à bb_servermessageop_ServerMessageOpOut.m_ConvertFrom(String t_json) dans e:\Projets\Jeux\Skirmish Commanders\Sources\MonkeyClient\skirmishclient.build\xna\MonkeyGame\MonkeyGame\Program.cs:ligne 6401
   à bb__SkirmishClient.m_HandleAsyncMessageResponse2(Int32 t_opCode, Int32 t_token, bb_sentasyncquery_SentAsyncQuery t_associatedSentQuery, String t_jsonResponse) dans e:\Projets\Jeux\Skirmish Commanders\Sources\MonkeyClient\skirmishclient.build\xna\MonkeyGame\MonkeyGame\Program.cs:ligne 4560
   à bb__SkirmishClient.m_OnMessageReceived(String t_message) dans e:\Projets\Jeux\Skirmish Commanders\Sources\MonkeyClient\skirmishclient.build\xna\MonkeyGame\MonkeyGame\Program.cs:ligne 4661
   à bb_websocketclient_WebSocketClient.OnMessageReceived(String t_message) dans e:\Projets\Jeux\Skirmish Commanders\Sources\MonkeyClient\skirmishclient.build\xna\MonkeyGame\MonkeyGame\Program.cs:ligne 5481
   à MkWebSockets.websocket_MessageReceived(Object sender, MessageReceivedEventArgs e) dans e:\Projets\Jeux\Skirmish Commanders\Sources\MonkeyClient\skirmishclient.build\xna\MonkeyGame\MonkeyGame\Program.cs:ligne 2291
   à WebSocket4Net.WebSocket.FireMessageReceived(String message)
   à WebSocket4Net.Command.Text.ExecuteCommand(WebSocket session, WebSocketCommandInfo commandInfo)
   à WebSocket4Net.WebSocket.ExecuteCommand(WebSocketCommandInfo commandInfo)
   à WebSocket4Net.WebSocket.OnDataReceived(Byte[] data, Int32 offset, Int32 length)
   à WebSocket4Net.WebSocket.client_DataReceived(Object sender, DataEventArgs e)
   à SuperSocket.ClientEngine.ClientSession.OnDataReceived(Byte[] data, Int32 offset, Int32 length)
   à SuperSocket.ClientEngine.AsyncTcpSession.ProcessReceive(SocketAsyncEventArgs e)
   à SuperSocket.ClientEngine.AsyncTcpSession.SocketEventArgsCompleted(Object sender, SocketAsyncEventArgs e)
   à System.Net.Sockets.SocketAsyncEventArgs.OnCompleted(SocketAsyncEventArgs e)
   à System.Net.Sockets.SocketAsyncEventArgs.ExecutionCallback(Object ignored)
   à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   à System.Net.Sockets.SocketAsyncEventArgs.FinishOperationSuccess(SocketError socketError, Int32 bytesTransferred, SocketFlags flags)
   à System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
   à System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)Process ended with return code 0 at 2/12/2013 11:50:50 PM


This seem to crash when the trace is huge.. but i may be wrong.. however this is what ive observed. The code work perfectly on HTML 5.


Rushino(Posted 2013) [#2]
Just to show this is really random here another stack trace... but this time it got caught by monkey.

Temps ‚coul‚ 00:00:00.92
Monkey Runtime Error : L'index était hors limites. Il ne doit pas être négatif et doit être inférieur à la taille de la collection.
Exception non gérée : System.ArgumentOutOfRangeException: L'index était hors limites. Il ne doit pas être négatif et doit être inférieur à la taille de la collection.
Nom du paramètre : index
   à System.ThrowHelper.ThrowArgumentOutOfRangeException()
   à System.Collections.Generic.List`1.get_Item(Int32 index)
   à bb_std_lang.popErr() dans e:\Projets\Jeux\Skirmish Commanders\Sources\MonkeyClient\skirmishclient.build\xna\MonkeyGame\MonkeyGame\Program.cs:ligne 153
   à bb_websocketclient_WebSocketClient.OnOpen() dans e:\Projets\Jeux\Skirmish Commanders\Sources\MonkeyClient\skirmishclient.build\xna\MonkeyGame\MonkeyGame\Program.cs:ligne 5462
   à MkWebSockets.websocket_Opened(Object sender, EventArgs e) dans e:\Projets\Jeux\Skirmish Commanders\Sources\MonkeyClient\skirmishclient.build\xna\MonkeyGame\MonkeyGame\Program.cs:ligne 2302
   à WebSocket4Net.WebSocket.OnHandshaked()
   à WebSocket4Net.Command.Handshake.ExecuteCommand(WebSocket session, WebSocketCommandInfo commandInfo)
   à WebSocket4Net.WebSocket.ExecuteCommand(WebSocketCommandInfo commandInfo)
   à WebSocket4Net.WebSocket.OnDataReceived(Byte[] data, Int32 offset, Int32 length)
   à WebSocket4Net.WebSocket.client_DataReceived(Object sender, DataEventArgs e)
   à SuperSocket.ClientEngine.ClientSession.OnDataReceived(Byte[] data, Int32 offset, Int32 length)
   à SuperSocket.ClientEngine.AsyncTcpSession.ProcessReceive(SocketAsyncEventArgs e)
   à SuperSocket.ClientEngine.AsyncTcpSession.SocketEventArgsCompleted(Object sender, SocketAsyncEventArgs e)
   à System.Net.Sockets.SocketAsyncEventArgs.OnCompleted(SocketAsyncEventArgs e)
   à System.Net.Sockets.SocketAsyncEventArgs.ExecutionCallback(Object ignored)
   à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   à System.Net.Sockets.SocketAsyncEventArgs.FinishOperationSuccess(SocketError socketError, Int32 bytesTransferred, SocketFlags flags)
   à System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
   à System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)Nom du paramètre : index




Rushino(Posted 2013) [#3]
I forgot to mention this is on monkey version 65. Sometime this happen, sometime not. Very nasty..


Rone(Posted 2013) [#4]
Did you enable CLR Exceptions in Debug/Exceptions...

It happens in 'WebSocket4Net', so probably no monkey issue. Looks like a concurrency problem-


Rushino(Posted 2013) [#5]
Umm. So you saying its a threading problem ? Probably WebSocket4Net use his own thread... which cause this. However this look to me that the errors stacktrace list getting access by 2 differents threads which cause the crash. I guess there should be some kind of locking mechanism in xna native code ?

Ive decided to make a run in the native visual studio IDE and ive discovered this.



It seem that there a bunches of NULL in the errStack which i am pretty sure is why it crash.

EDIT: I Added some condition check to avoid getting this problem but now i get this.



Why does it call Run a second time ? this is not related to WebSocket4Net.

Only Mark can confirm.. from where exactly this problem is coming.


Rone(Posted 2013) [#6]
If your WebSocket4Net eventhandler runs monkey code in antother thread, it's conforming to expectations that this will brake the 'errStack'.

Collect your WebSocket4Net events and call the eventhandlers in the main thread.

What kind of condition check??

A quick workaround could be to lock errStack in popErr/pushErr/StackTrace...
But you'll save yourself a lot of problems if you do this not asynchronously


Rushino(Posted 2013) [#7]
How would it run monkey code in another thread ? I though it was all running on the same thread. Umm.. could it happen that WebSocket4Net run in his own thread and when calling the eventhandlers.. it actually call them in his own thread outside monkey thread ? if this is the case then i don't see how i will be able to fix this issue except that i could litterally collect the data received in a list and then handle this specific list. Instead of doing all the operations in the event handlers. EDIT: Just tried keep crashing..

Collect your WebSocket4Net events and call the eventhandlers in the main thread.


Isn't that what i am already doing ? I mean see the code above.

Global webSocketInstance:WebSocketClient
Global clientContext:SkirmishClient

<...>

'summary: Fonction de démarrage.
Function Main:Int()
	clientContext = New SkirmishClient()
	Return 0
End

<...>

Class SkirmishClient Extends App

	Method OnMessageReceived:Void(message:String) ' Event coming from the webSocketInstance object.

		<...>
		
		' Vérifier si les données JSON représente un message du serveur.
		If Not (queryMessageReceived.ContainMessageReturnCode())
			SendToLog("Query: CALLING OPERATION " + queryMessageReceived.OpCode + " with token " + queryMessageReceived.Token + " -> HandleAsyncJsonResponse")
			HandleAsyncJsonResponse(queryMessageReceived.OpCode, queryMessageReceived.Token, associatedSentQuery, queryMessageReceived.Json)
		Else
			SendToLog("Query: CALLING OPERATION " + queryMessageReceived.OpCode + " with token " + queryMessageReceived.Token + " -> HandleAsyncMessageResponse")
			HandleAsyncMessageResponse(queryMessageReceived.OpCode, queryMessageReceived.Token, associatedSentQuery, queryMessageReceived.Json)
		End If
						
		<...>

	End
	
	Method OnClose:Void(code:Int, reason:String)
	End
	
	Method OnError:Void(error:String)
	End
	
	<...>
End

<...>

	Method HandleMessageResponse:Void(opCode:Int, jsonResponse:String)
		Local operation:IHandleMessageResponse = IHandleMessageResponse(Self.availableOperations.Get(opCode))
		If operation <> Null Then
			Local serverMessage:ServerMessageOpOut = New ServerMessageOpOut()
			serverMessage.ConvertFrom(jsonResponse)
			operation.HandleMessageResponse(serverMessage)
		Else
			Throw New Exception("L'opération " + opCode + " n'implémente pas l'interface IHandleMessageResponse. " +
								"Elle ne peut donc pas gérer ce type de réponse.", "skirmishclient", "HandleMessageResponse")
		End If
	End
	
	Method HandleAsyncMessageResponse:Void(opCode:Int, token:Int, associatedSentQuery:SentAsyncQuery, jsonResponse:String)
		Local operation:IHandleAsyncMessageResponse = IHandleAsyncMessageResponse(Self.availableOperations.Get(opCode))
		If operation <> Null Then
			Local serverMessage:ServerMessageOpOut = New ServerMessageOpOut()
			serverMessage.ConvertFrom(jsonResponse)
			operation.HandleAsyncMessageResponse(associatedSentQuery, token, serverMessage)
		Else
			Throw New Exception("L'opération " + opCode + " n'implémente pas l'interface IHandleAsyncMessageResponse. " +
								"Elle ne peut donc pas gérer ce type de réponse.", "skirmishclient", "HandleAsyncMessageResponse")
		End If
	End

<...>

Class WebSocketClient Extends MkWsObject Implements IDebuggable

Private
	
	Field lastState:Int
	
Public
	
	Method New()
	End
	
	Method OnMessageReceived:Void(message:String)
		clientContext.SendToLog("MessageReceived: " + message)
		clientContext.OnMessageReceived(message)
		UpdateLastState()
	End
	
<...>



marksibly(Posted 2013) [#8]
I'm guessing this is a WebSocket/threading issue, possibly caused by messages being received on a different thread.

Monkey is not multithreaded, and while you may be able to fix the 'errStack' issue (eg: run in release mode!) there will likely be other issues.

The 'right' way to do this would be to collect received messages (in native code) for delivery in main/gui thread (to monkey code).


Rushino(Posted 2013) [#9]
@marksibly

Thanks a lots for your reply.

So basically i collect them in the native library ? then using some kind of method i get them from the native lib ?

Are native types such string[] supported when getting something from native ?


Rushino(Posted 2013) [#10]
@marksibly

I tested your solution and the good news is that it seem to work perfectly. It seem that this is not a very good idea to make a lib execute virtual method from the inside of the lib. Umm.. i think its time to get back to work on my websocket lib. To be honest, i had worked on it on the surface so i didn't seen this kind of problems could happen. So what i will do is encapsulate all the features of WebSockets inside a module and operate from this specific module. I will do the same in HTML5 platform too.

Also i wanted to say a big THANKS YOU (and rone too :)) for helping me out. I was about to drop this target because it was troublesome lately. Hopefully i didn't cause a lots of users still use Win7. Also i can't wait to try the Win8 target. Just got a Surface Pro from Microsoft so i will be working to release it on this target too. WebSockets seem to be fully integrated to Win8 API.

Thanks again!