Hi J-S,

Although you plan on resubmitting this after the next release, I wanted to make a comment now so as not to miss it later.

There's a race condition in the unref() code. The pointer passed in to s_allocationObserver on line 213 may reference a deleted object. Specifically, a second thread can interrupt this thread immediately after it decrements the reference count, and unref the object to delete it before the first thread regains control. To be safe, this call should be moved to the top of the function, before decrementing the refCount.

Regards,

Mark

Jean-Sébastien Guay wrote:
Hi Robert,

(it might not be a good time for this, so if you want to push this discussion to after 2.8, it's fine by me)

In light of my recent ordeal with looking for "memory leaks" (i.e. cycles and other ref counting issues), I was wondering if you would accept some changes to osg::Referenced which made it a bit easier to find the source of the problem.

Just to be clear, this is more of a request for comments than a real submission. All I'm saying is that this was useful to me, so it might be useful to others, perhaps with some modifications.

See the attached files. It's pretty self-explanatory. Basically, if you want you can register a callback object with osg::Referenced, which will be called :

* when a new osg::Referenced is created
* when an osg::Referenced is destroyed
* when ref() is called on an osg::Referenced
* when unref() is called on an osg::Referenced
* when unref_nodelete() is called on an osg::Referenced

each time passing the osg::Referenced object. Then the observer can do what it wants at any or all of these points.

In my case, I recorded a call stack to keep track of all events, and then I could dump the events I wanted to see to a file. And since I recorded the events in maps keyed by osg::Referenced pointer, I could easily do differences between one state and another.

It won't do all the work for you (in my case, I had to code the part that records the call stack which is platform- and compiler-specific, and the parts in my application that dumped the stacks to file, and then I had to analyse those stacks to see which objects were still live and why) but it's a good tool I think.

Then, of course, there's the issue of performance. First of all, if there's no registered observer, there will be one check per operation (ctor, dtor, ref, unref, unref_nodelete). But this is only if it's enabled in the osg::Referenced header via two #defines (which are commented by default), one for allocation/destruction (which was already there) and one for refs and unrefs. So you can control which events you want to get. If these are not enabled, then there is no performance penalty. The difference will be just one static pointer in osg::Referenced.

So, comments? I don't think this is an exaggerated amount of code to add, and it was certainly useful to me. But I could see how you might argue that if no one has needed this before, it might not be generally useful. If you agree with the principle but not the execution, please comment and I'll try and improve the code.

Thanks,

J-S
------------------------------------------------------------------------

_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to