[osg-users] [osgPlugins] Lua: deterministic destruction of the script engine / leaks caused by circular references

Robert Osfield robert.osfield at gmail.com
Fri Sep 20 01:12:53 PDT 2019

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.


On Thu, 19 Sep 2019 at 22:29, Hannes Pabst <johannes.pabst at ocilion.com>

> 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 at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openscenegraph.org/pipermail/osg-users-openscenegraph.org/attachments/20190920/c416d051/attachment.html>

More information about the osg-users mailing list