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

2019-09-20 Thread Robert Osfield
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 
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 luaScriptEngine =
> osgDB::readFile("ScriptEngine.lua");
>osg::ref_ptr 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


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

2019-09-19 Thread Hannes Pabst
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 luaScriptEngine = 
osgDB::readFile("ScriptEngine.lua");
   osg::ref_ptr 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