Bug Report: Removing a FrameListener null ref exception

Clay

21-03-2008 23:45:56

I've run into a problem... Say you add a FrameListener:

root.FrameStarted += new FrameListener.FrameStartedHandler(TestListener);
From this frame listener if you to remove itself, you get a NullReferenceException. Here is the code:
static bool TestListener(FrameEvent evt)
{
Mogre.Root.Singleton.FrameStarted -= new FrameListener.FrameStartedHandler(TestListener);
return true;
}

This gives a NullReferenceException with this callstack:
at Mogre.Root.remove_FrameStarted(FrameStartedHandler hnd)
at MogrePython.Program.TestListener(FrameEvent evt) in C:\Users\clay\Documents\Visual Studio 2008\Projects\MogrePython\MogrePython\Program.cs:line 34
at Mogre.Root.raise_FrameStarted(FrameEvent evt)
at Mogre.Root.OnFrameStarted(FrameEvent evt)
at Mogre.FrameListener_Director.frameStarted(FrameListener_Director* , FrameEvent* evt)
at Ogre.Root.renderOneFrame(Root* )
at Mogre.Root.RenderOneFrame()
at MogrePython.OgreWindow.Go() in C:\Users\clay\Documents\Visual Studio 2008\Projects\MogrePython\MogrePython\OgreWindow.cs:line 81
at MogrePython.Program.Main() in C:\Users\clay\Documents\Visual Studio 2008\Projects\MogrePython\MogrePython\Program.cs:line 21
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()


Marioko, could you take a look at this? I can't quite tell what the problem is from looking at the C++/CLI code.

Thanks,
-Clay

Marioko

22-03-2008 02:01:44

mmm first of all, why do you need self remove callback??? why instead use some other callback to kill it???

Callback2 kill Callback1, or something like that..

That is strange error, i will try to see what is happen in C++/CLI!! :D

Clay

22-03-2008 04:06:53

mmm first of all, why do you need self remove callback??? why instead use some other callback to kill it???
I'm trying to enable a very specific scenario... I have a decorator function in python which shields Ogre from exceptions thrown by the FrameListener:
def SafeFrameListener(listener):
def InnerFunction(evt):
try:
return listener(evt)
except Exception, e:
clr.AddReferenceByPartialName("System.Windows.Forms")
from System.Windows.Forms import MessageBox
MessageBox.Show(str(e), "An exception occurred!");

Ogre.Root.Singleton.FrameStarted -= InnerFunction
Ogre.Root.Singleton.FrameEnded -= InnerFunction

return True
return InnerFunction

Let's say there was a function like this:
def Listener(evt):
Error() # Let's say this throws an exception
return True

Mogre.Root.Singleton.FrameStarted += Listener

If you ran the above code, and added this listener, it would take down your application... Instead, if you apply the above decorator you would get a MessageBox that pops up telling you an error occurred, what the error was, then removes the function so it stops throwing exceptions. The only difference would be this:

@SafeFrameListener
def Listener(evt):
Error() # Let's say this throws an exception
return True

Mogre.Root.Singleton.FrameStarted += Listener

As long as you add @SafeFrameListener to decorate any Listener, you don't have to worry about an exception unwinding the stack. This is important when you are using a scripting language because a simple typo causes an unrecoverable error in a FrameListener...

I could rewrite it to display the error message once then silently handle/ignore the exception, but that's ugly, difficult, and hacky. =)