Hi Hannes, Thanks for detailing the issue so clearly. On a first pass it would seem like your suggesting of changing to observer_ptr<> would be appropriate. I'll need to properly review it, though I'm working flat out on the VSG right now so can't jump in right away. Could you make a PR for your fix, then once I get a breather from the VSG work can jump in a test out the issue and the solution.
Cheers, Robert. On Thu, 19 Sep 2019 at 22:29, Hannes Pabst <johannes.pa...@ocilion.com> wrote: > Consider the following Lua script: > > > Code: > > function makeObjectWithCallback() > local object = new "osg::Object" > > function object:process() > print "Hello" > end > > return object > end > > > > > The function makeObjectWithCallback will create an osg::Object which has a > LuaCallbackObject named "process", stored within its user data. > The LuaCallbackObject itself stores an ref_ptr to the LuaScriptEngine for > being able to call the function defined within Lua. > Unfortunately the references now are circular: > > LuaScriptEngine -> Lua -> Object -> LuaCallbackObject -> LuaScriptEngine > > Once the script is executed it is hard to get rid of the LuaScriptEngine > object. > Simply deleting all references to the ScriptEngine and the returned Object > on the cpp side will cause a leak, as the Lua state keeps them alive. > Even if the variable "object" above is only temporarily used in Lua, a GC > run is necessary to break the Lua -> Object dependency. > But who shall trigger that, if all references on the cpp side are gone and > Lua cannot be called anymore? > > Here is the code to run the Lua script above, that will produce the leak: > > > Code: > > void runScript() > { > osg::ref_ptr<osg::ScriptEngine> luaScriptEngine = > osgDB::readFile<osg::ScriptEngine>("ScriptEngine.lua"); > osg::ref_ptr<osg::Script> script = osgDB::readScriptFile("script.lua"); > osg::Parameters inputParameters; > osg::Parameters outputParameters; > luaScriptEngine->run(script.get(), "makeObjectWithCallback", > inputParameters, outputParameters); > } > > > > > My intention is to use LuaCallbackObjects but also to have the possibility > to clean up and reload the Lua script at any time by re-instantiating the > LuaScriptEngine. > Unfortunately there seems to be no general and easy way to destroy the > shared LuaScriptEngine object. > > Wouldn't it be a more practical design to have the LuaCallbackObject only > weakly reference the LuaScriptEngine? > If the ScriptEngine object is gone, callbacks into Lua could simply do > nothing – per definition. > I understand such change would break existing code, in situations where > one creates a LuaScriptEngine object on the fly running a script that hooks > to the OSG runtime system. > As far as I understand the Lua plugin code, the lua_close call in the > destructor of LuaScriptEngine releases all references held by Lua and thus > would be able break up all other eventually existing circular references - > so the class would in principle be ready to act as a “master object” on the > cpp side, that is able to control the lifetime of the whole Lua system. > > I have made this change to the Lua plugin code (simply by replacing the > ref_ptr by an observer_ptr) and for my purposes it seems to work well, but > wonder if this is an issue that should generally be addressed within OSG. > > ------------------ > Read this topic online here: > http://forum.openscenegraph.org/viewtopic.php?p=76703#76703 > > > > > > _______________________________________________ > osg-users mailing list > osg-users@lists.openscenegraph.org > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org >
_______________________________________________ osg-users mailing list osg-users@lists.openscenegraph.org http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org