Game Development Community

TX2D 3.1.5 Beta - Silencing events can cause crashes (Xbox Code 4)

by Giuseppe De Francesco · in Torque X 2D · 06/09/2010 (1:59 am) · 14 replies

Build: 3.1.5 Beta

Platform: Any

Target: Engine Core (Core/TorqueEvents.cs)

Issues: Because of some racing issue silencing/re-listening to events can cause the game to crash at random.

Steps to Repeat:
Difficult to repro:
1. Create a TX project
2. Quickly silence end listen to an event (input dor instance)
3. At runtime the game might crash

Suggested Fix:
in Core/TorqueEvents.cs (line 636) change this

ev._Trigger(node._consumer);

to this:

if (node._consumer != null)
ev._Trigger(node._consumer);

About the author

In the software eng. field since 1981, in charge of R&D during last 10 years. IEEE Senior Member (and volunteer).


#1
06/25/2010 (10:02 am)
This is still a bug in the new beta.
#2
06/25/2010 (3:27 pm)
Logged as TQA-429.
#3
06/29/2010 (4:28 pm)
@Pino
Can you provide some more detail on how you're getting this crash? I haven't been able to reproduce this one at all.
#4
06/29/2010 (6:19 pm)
Hey Scott,

that's a racing condition experimented by Matthew, you can find more details here: http://www.xp-dev.com/forum/topic/2749.

~Pino
#5
06/30/2010 (5:29 pm)
This should be fixed in the next release =)
#6
08/12/2010 (6:28 am)
Heya, I just ran into a problem with the event system crashing again. I'm not sure if its related but it seams to be a race condition. I get this crash rarely (1 in 300) just after loading a level.


I get a null reference error on "trigger" in this method:
internal override void _Trigger(Delegate d)
        {
            if (d == null)
                return;

            TorqueEventDelegate<T> trigger = d as TorqueEventDelegate<T>;
            trigger(Name, _value);
        }




Call Stack:

> GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEvent<int>._Trigger(System.Delegate d = {Method = {Void BlinkEventHandler(System.String, Boolean)}}) Line 88 C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager._TriggerEvent(GarageGames.Torque.Core.TorqueEventManager.TorqueEventBase ev = {GarageGames.Torque.Core.TorqueEvent<int>}) Line 640 + 0xe bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager.MgrTriggerEvent<int>(GarageGames.Torque.Core.TorqueEvent<int> ke = {GarageGames.Torque.Core.TorqueEvent<int>}, int data = 2) Line 505 + 0xb bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager.TriggerEvent<int>(GarageGames.Torque.Core.TorqueEvent<int> ke = {GarageGames.Torque.Core.TorqueEvent<int>}, int data = 2) Line 331 + 0x18 bytes C#
Game.exe!ChuDynasty.ai.trible.GodFocusComponent.ProcessTick(GarageGames.Torque.Sim.Move move = null, float dt = 0.03) Line 46 + 0x11 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Sim.ProcessList._TickObjects(float tickSec = 0.03) Line 736 + 0x34 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Sim.ProcessList.AdvanceTick(float floatMS = 30.0) Line 517 + 0x1c bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.XNA.TorqueEngineComponent._UpdateSim(string eventName = "TimeEvent", float elapsed = 30.0) Line 895 + 0x24 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEvent<float>._Trigger(System.Delegate d = {Method = {Void _UpdateSim(System.String, Single)}}) Line 88 + 0x25 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager._TriggerEvent(GarageGames.Torque.Core.TorqueEventManager.TorqueEventBase ev = {GarageGames.Torque.Core.TorqueEvent<float>}) Line 640 + 0xe bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager.MgrProcessEvents() Line 480 + 0x21 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager.ProcessEvents() Line 318 + 0x12 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.XNA.TorqueEngineComponent.Update(Microsoft.Xna.Framework.GameTime gameTime = {Microsoft.Xna.Framework.GameTime}) Line 506 + 0x5 bytes C#
#7
08/12/2010 (10:34 am)
Hey Matt,

the stack trace looks good to me: as you see the method has been properly casted and called (Void BlinkEventHandler(System.String, Boolean)) so I guess the problem here is caused by the values of the delegate's parameters, not by the the _Trigger engine's method. You should have a look to those values when the error is raised to understand why it crashes.
#8
08/13/2010 (8:00 pm)
Heya Pino. I'm not following totally sorry. Are you thinking that the "string" or bool passed into the Blink Event are causing the problem?

Thanks again!
#9
08/13/2010 (9:32 pm)
Yep,

i.e. the string could be null.
#10
08/24/2010 (4:25 am)
Heya, Found another weirdness in the event system. Perhapes I'm doing something wrong but I'm not sure what.

So on load my event went into an infinite loop. The event is called when a particular condition is met in the process tick of my component. I've put in break points and verified that it only gets called from my code once. However the system is acting like its getting called every Tick.

Stack with my Break Point:
> Game.exe!ChuDynasty.graphic.EyeFollowComponent.ChangeFocusEventHandler(string eventName = "GodFocus", int t = 1) Line 159 C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEvent<int>._Trigger(System.Delegate d = {Method = {Void ChangeFocusEventHandler(System.String, Int32)}}) Line 89 + 0x25 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager._TriggerEvent(GarageGames.Torque.Core.TorqueEventManager.TorqueEventBase ev = {GarageGames.Torque.Core.TorqueEvent<int>}) Line 641 + 0xe bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager.MgrTriggerEvent<int>(GarageGames.Torque.Core.TorqueEvent<int> ke = {GarageGames.Torque.Core.TorqueEvent<int>}, int data = 1) Line 506 + 0xb bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager.TriggerEvent<int>(GarageGames.Torque.Core.TorqueEvent<int> ke = {GarageGames.Torque.Core.TorqueEvent<int>}, int data = 1) Line 332 + 0x18 bytes C#
Game.exe!ChuDynasty.ai.trible.GodFocusComponent.ProcessTick(GarageGames.Torque.Sim.Move move = null, float dt = 0.03) Line 46 + 0x11 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Sim.ProcessList._TickObjects(float tickSec = 0.03) Line 736 + 0x34 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Sim.ProcessList.AdvanceTick(float floatMS = 30.0) Line 517 + 0x1c bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.XNA.TorqueEngineComponent._UpdateSim(string eventName = "TimeEvent", float elapsed = 30.0) Line 895 + 0x24 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEvent<float>._Trigger(System.Delegate d = {Method = {Void _UpdateSim(System.String, Single)}}) Line 89 + 0x25 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager._TriggerEvent(GarageGames.Torque.Core.TorqueEventManager.TorqueEventBase ev = {GarageGames.Torque.Core.TorqueEvent<float>}) Line 641 + 0xe bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager.MgrProcessEvents() Line 481 + 0x21 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager.ProcessEvents() Line 319 + 0x12 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.XNA.TorqueEngineComponent.Update(Microsoft.Xna.Framework.GameTime gameTime = {Microsoft.Xna.Framework.GameTime}) Line 506 + 0x5 bytes C#
[External Code]
Game.exe!ChuDynasty.Game.Update(Microsoft.Xna.Framework.GameTime gameTime = {Microsoft.Xna.Framework.GameTime}) Line 582 + 0xc bytes C#
[External Code]
Game.exe!ChuDynasty.Game.Main() Line 191 + 0xe bytes C#


#11
08/24/2010 (4:26 am)
This stack is when using break all to get out of the infinite loop.

GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueObjectDatabase.FindObject<GarageGames.Torque.T2D.T2DSceneObject>(string name = "_player1") Line 570 + 0x14 bytes C#
Game.exe!ChuDynasty.graphic.EyeFollowComponent.ChangeFocusEventHandler(string eventName = "GodFocus", int t = 1) Line 170 + 0x29 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEvent<int>._Trigger(System.Delegate d = {Method = {Void ChangeFocusEventHandler(System.String, Int32)}}) Line 89 + 0x25 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager._TriggerEvent(GarageGames.Torque.Core.TorqueEventManager.TorqueEventBase ev = {GarageGames.Torque.Core.TorqueEvent<int>}) Line 641 + 0xe bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager.MgrTriggerEvent<int>(GarageGames.Torque.Core.TorqueEvent<int> ke = {GarageGames.Torque.Core.TorqueEvent<int>}, int data = 1) Line 506 + 0xb bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager.TriggerEvent<int>(GarageGames.Torque.Core.TorqueEvent<int> ke = {GarageGames.Torque.Core.TorqueEvent<int>}, int data = 1) Line 332 + 0x18 bytes C#
Game.exe!ChuDynasty.ai.trible.GodFocusComponent.ProcessTick(GarageGames.Torque.Sim.Move move = null, float dt = 0.03) Line 46 + 0x11 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Sim.ProcessList._TickObjects(float tickSec = 0.03) Line 736 + 0x34 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Sim.ProcessList.AdvanceTick(float floatMS = 30.0) Line 517 + 0x1c bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.XNA.TorqueEngineComponent._UpdateSim(string eventName = "TimeEvent", float elapsed = 30.0) Line 895 + 0x24 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEvent<float>._Trigger(System.Delegate d = {Method = {Void _UpdateSim(System.String, Single)}}) Line 89 + 0x25 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager._TriggerEvent(GarageGames.Torque.Core.TorqueEventManager.TorqueEventBase ev = {GarageGames.Torque.Core.TorqueEvent<float>}) Line 641 + 0xe bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager.MgrProcessEvents() Line 481 + 0x21 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.Core.TorqueEventManager.ProcessEvents() Line 319 + 0x12 bytes C#
GarageGames.TorqueX.Framework.dll!GarageGames.Torque.XNA.TorqueEngineComponent.Update(Microsoft.Xna.Framework.GameTime gameTime = {Microsoft.Xna.Framework.GameTime}) Line 506 + 0x5 bytes C#
[External Code]
Game.exe!ChuDynasty.Game.Update(Microsoft.Xna.Framework.GameTime gameTime = {Microsoft.Xna.Framework.GameTime}) Line 582 + 0xc bytes C#
[External Code]
Game.exe!ChuDynasty.Game.Main() Line 191 + 0xe bytes C#
#12
08/24/2010 (5:03 am)
Ok I found a perfect re-pro for the null reference error. If I load a level that dosn't use the event and then unload it. Then load a level that does use the event I get a crash every time.

It seams that the variables passed by the event are not null. I pass 2 variables a string and a int. The string is == "GodBlink" the int == 2.

What I am doing is creating an event in the OnRegister of a "GodFocusComponent" and a event listener in the OnRegister of 2 "EyeFollowComponents". It seams that for some reason it doesn't like what I'm doing.

In this particular instance its easy for me to work around this issue. I don't really need events. I wanted to post this problem encase it is actually a bug that needs fixing. :)
#13
08/24/2010 (7:14 am)
Hey Matt, can you send me the repro? I did try to repro this one but without luck.
#14
08/25/2010 (3:27 am)
I'll try to build a repro project and send it over. :) Thanks Pino.