Howto:Troubleshooting Nasal Callbacks

From FlightGear wiki
Jump to navigation Jump to search

Background

Cquote1.png Someone recently pointed out that the setlistener() / removelistener() API makes it easy to leak resources. So I wondered about making an alternate API where the return value from setlistener must be kept, or the listener is removed. I can imagine this with a helper object
var myL = setlistener2("some/prop", func { ... }} )

myL.addprop("some/other/prop");

myL.addprop("yet/another/prop");

Now you need to retain a ref to myL or the listeners on all the props are removed. I don't think we can retro-fit this to the existing API, because I suspect many places just ignore the return value and would break with this change. (Or even pass a vec of property names to setlistener2, to avoid all the discrete calls to 'addprop', that's a seperate detail really)

It seems like this would work, and be easy enough to implement - question is if it gives enough benefit to be worth the confusion.
— zakalawe (Oct 28th, 2013). Listener objects.
(powered by Instant-Cquotes)
Cquote2.png
Cquote1.png usually, "events" means Nasal callbacks (timers) - however, it's also often not just Nasal per se, but misuse of timers - in general, settimer() is a API that is prone to being used improperly, because it needs to be consciously used, i.e. to enable/disable loops and to prevent them from being "registered" (invoked) too often - which is the most common pattern of misuse we've seen so far: Nasal based callbacks that end up being invoked doens (or even hundreds) of times despite being only intended to be invoked once per interval.

However, to be fair, this is not specific to Nasal - A few months ago, Torsten fixed pretty much the exact same bug in the C++ effects code which was registering thousands of identical callbacks. The underlying problem here is that the SGPropertyNode code does not currently support any form of troubleshooting, i.e. to do callback tracking - for details, refer to: Towards better troubleshooting

The maketimer() API can be used to help prevent such issues when using timers, but listeners are a completely different matter (if in doubt, please file a feature request)
— Hooray (Jan 31st, 2016). Re: 777 freezes and FPS loss.
(powered by Instant-Cquotes)
Cquote2.png

Objective

Implementation

We will be wrapping/overriding the problematic APIs at the global level to provide functions that internally support callback/registration tracking, and which can automatically detect improper use of these APIs:

<syntaxhighlight lang="nasal"> var setlistener = func() { };

var settimer = func() { }; </syntaxhighlight

Integration

The corresponding APIs should be either loaded globally via $FG_ROOT/Nasal or explicitly loaded via the -set.xml file:

<syntaxhighlight lang="xml"> </syntaxhighlight

Code