[osg-users] Is text thread safe in 2.0.0?

sherman wilcox wilcox.sherman at gmail.com
Tue Sep 4 22:40:51 PDT 2007


Success! Well, not that kind of success. You see, I was running the
osgText multithreaded sample you wrote...it would not crash. Ran
perfectly on all my systems. So......I crank up my app, which just so
happens has an option to update osgText objects on a background
thread. CRASH!!! Time and time again...crash! So, I spent most of the
night trying to debug this.

Long story shortened, I haven't figured out the crash BUT I have a
clue. If I introduce an earth model built using osgDem into your
osgText demo with about 10 threads running (probably will happen with
fewer, haven't tried) I get the same crash as I do in my app. I
suspect the problem has something to do with the databasepager.

Let me explain. The crash in the new --MT osgText demo (as well as in
my app) both die in:
osgText::Font::getGlyphImageMarginRatio()  Line 241 C++

Here's my call stack:
osgText.dll!osgText::Font::getGlyphImageMarginRatio()  Line 241 C++
> osgdb_freetype.dll!FreeTypeFont::setFontResolution(unsigned int width=60, unsigned int height=60)  Line 64 + 0x9 bytes C++
osgText.dll!osgText::Text::computeGlyphRepresentation()  Line 485 C++
osgText.dll!osgText::Text::setFont(osgText::Font * font=0x0828e2c8)
Line 119 + 0x7 bytes C++
osgText.dll!osgText::Text::setFont(const
std::basic_string<char,std::char_traits<char>,std::allocator<char> > &
fontfile="Arial.ttf")  Line 124 + 0x1a bytes C++


Here's the call stack from the osgText demo:
> osgText.dll!osgText::Font::getGlyphImageMarginRatio()  Line 241 C++
osgdb_freetype.dll!FreeTypeFont::setFontResolution(unsigned int
width=32, unsigned int height=32)  Line 64 + 0x9 bytes C++
osgText.dll!osgText::Text::computeGlyphRepresentation()  Line 485 C++
osgText.dll!osgText::Text::setText(const osgText::String & text={...})
 Line 165 + 0x7 bytes C++
osgText.dll!osgText::Text::setText(const
std::basic_string<char,std::char_traits<char>,std::allocator<char> > &
text=")]#œ<")  Line 170 + 0x1e bytes C++
osgtest.exe!UpdateTextOperation::load()  Line 561 C++
osgtest.exe!UpdateTextOperation::operator()(osg::Object *
callingObject=0x00000000)  Line 498 + 0x5 bytes C++
osg.dll!osg::OperationThread::run()  Line 416 C++
OpenThreads.dll!OpenThreads::ThreadPrivateActions::StartThread(void *
data=0x00f29f90)  Line 120 C++
msvcr80.dll!__endthreadex()  + 0x3b bytes
msvcr80.dll!__endthreadex()  + 0xc7 bytes
kernel32.dll!@BaseThreadInitThunk at 12()  + 0xe bytes
ntdll.dll!__RtlUserThreadStart at 8()  + 0x23 bytes

They both die in osgText::Font::getGlyphImageMarginRatio().

I'm wondering if there's a reference count problem somewhere that's
causing the Font object to be prematurely deleted? That is, the
"activeFont" object in Text::computeGlyphRepresentation is getting the
rug pulled out from under it. I say that because the databasepager
will call Registry::readImplementation(const ReadFunctor& readFunctor,
bool useObjectCache)   with useObjectCache as false...which clears the
cache which decrements the refcount on cached Font objects...sometimes
this decrement is fatal? Maybe? I dunno, maybe I'm grasping @ straws,
but I do know if you don't incorporate the database pager then things
seem to run fine.

Any ideas?

On 9/4/07, Robert Osfield <robert.osfield at gmail.com> wrote:
> Hi Sheman,
>
> Thanks for testing and changes.  I have added static Mutex directly
> into the DefaultFont::instance() method rather that add it the
> DefaultFont class.  It should provide the same effect but keep things
> a little bit neater.
>
> I have also added a mutex into Font::GlphTexture to marshal the
> addGlyph and texture apply.
>
> Could you do an svn update and let me know how you get on,
>
> Cheers.
> Robert.
>
> On 9/2/07, sherman wilcox <wilcox.sherman at gmail.com> wrote:
> > I spent a few moments digging into the crash I was having...looks like
> > a race condition in DefaultFont* DefaultFont::instance(). I wasn't
> > sure about the best course, but I thought the simplest solution was to
> > wrap that call with a mutex, which I did. After doing that, no more
> > crashes when I run --mt 10 in Release mode. I've attached the changes
> > defaultfont.h/.cpp.
> >
> > BUT...I still get crashes in debug mode @ --mt 10 The crashes are
> > easily reproduced. I left the code running for quite a while in
> > Release mode, didn't crash. Debug dies immediatly.
> >
> >
> > I've attached the changes defaultfont.h/.cpp.
> >
> >
> > Here's a call stack from the new crashes...in void
> > Font::GlyphTexture::apply(osg::State& state)  I noticed that the
> > elements in the _glyphs container had bad _font objects...these _font
> > objects had addresses of 0xcdcdcdcd. Not sure at what point things
> > went off into the weeds.
> >
> > Stack trace from most recent crash:
> >
> > >       osgTextd.dll!std::_Vector_const_iterator<osg::ref_ptr<osgText::Font::Glyph>,std::allocator<osg::ref_ptr<osgText::Font::Glyph>
> > > >::operator++()  Line 117 + 0x33 bytes        C++
> >         osgTextd.dll!osgText::Font::GlyphTexture::apply(osg::State &
> > state={...})  Line 653 + 0x8 bytes      C++
> >         osgd.dll!osg::State::applyAttribute(const osg::StateAttribute *
> > attribute=0x0195c730, osg::State::AttributeStack & as={...})  Line
> > 1158 + 0x13 bytes       C++
> >         osgd.dll!osg::State::applyTextureAttribute(unsigned int unit=0,
> > const osg::StateAttribute * attribute=0x0195c730)  Line 337 + 0x10
> > bytes   C++
> >         osgTextd.dll!osgText::Text::renderOnlyForegroundText(osg::State &
> > state={...}, const osg::Vec4f & colorMultiplier={...})  Line 1971 +
> > 0x1d bytes      C++
> >         osgTextd.dll!osgText::Text::drawImplementation(osg::State &
> > state={...}, const osg::Vec4f & colorMultiplier={...})  Line 1587       C++
> >         osgTextd.dll!osgText::Text::drawImplementation(osg::RenderInfo &
> > renderInfo={...})  Line 1471    C++
> >         osgd.dll!osg::Drawable::draw(osg::RenderInfo & renderInfo={...})
> > Line 868 + 0x13 bytes   C++
> >         osgUtild.dll!osgUtil::RenderLeaf::render(osg::RenderInfo &
> > renderInfo={...}, osgUtil::RenderLeaf * previous=0x09837b28)  Line 60
> > + 0x19 bytes    C++
> >         osgUtild.dll!osgUtil::RenderBin::drawImplementation(osg::RenderInfo
> > & renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28)  Line
> > 408 + 0x19 bytes        C++
> >         osgUtild.dll!osgUtil::RenderBin::draw(osg::RenderInfo &
> > renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28)  Line
> > 373 + 0x17 bytes        C++
> >         osgUtild.dll!osgUtil::RenderBin::drawImplementation(osg::RenderInfo
> > & renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28)  Line
> > 458 + 0x35 bytes        C++
> >         osgUtild.dll!osgUtil::RenderStage::drawImplementation(osg::RenderInfo
> > & renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28)  Line
> > 1053    C++
> >         osgUtild.dll!osgUtil::RenderBin::draw(osg::RenderInfo &
> > renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28)  Line
> > 373 + 0x17 bytes        C++
> >         osgUtild.dll!osgUtil::RenderStage::drawInner(osg::RenderInfo &
> > renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28, bool &
> > doCopyTexture=false)  Line 722  C++
> >         osgUtild.dll!osgUtil::RenderStage::draw(osg::RenderInfo &
> > renderInfo={...}, osgUtil::RenderLeaf * & previous=0x09837b28)  Line
> > 913 + 0x1b bytes        C++
> >         osgUtild.dll!osgUtil::SceneView::draw()  Line 1456 + 0x34 bytes C++
> >         osgViewerd.dll!osgViewer::Renderer::draw()  Line 382 + 0xf bytes        C++
> >         osgViewerd.dll!osgViewer::Renderer::operator()(osg::GraphicsContext
> > * context=0x01926430)  Line 573 C++
> >         osgd.dll!osg::GraphicsContext::runOperations()  Line 671 + 0x33 bytes   C++
> >         osgd.dll!osg::RunOperations::operator()(osg::GraphicsContext *
> > context=0x01926430)  Line 135   C++
> >         osgd.dll!osg::GraphicsOperation::operator()(osg::Object *
> > object=0x01926430)  Line 50 + 0x19 bytes        C++
> >         osgd.dll!osg::OperationThread::run()  Line 413 + 0x26 bytes     C++
> >         osgd.dll!osg::GraphicsThread::run()  Line 40    C++
> >         OpenThreadsd.dll!OpenThreads::ThreadPrivateActions::StartThread(void
> > * data=0x018f9740)  Line 106 + 0xf bytes        C++
> >         msvcr80d.dll!__beginthreadex()  + 0x221 bytes
> >         msvcr80d.dll!__beginthreadex()  + 0x1c7 bytes
> >         kernel32.dll!@BaseThreadInitThunk at 12()  + 0xe bytes
> >         ntdll.dll!__RtlUserThreadStart at 8()  + 0x23 bytes
> >
> >
> >
> >
> >
> >
> > Here's the debug call stack of the original crash:
> >
> > osgTextd.dll!osg::ref_ptr<osg::StateSet>::get()  Line 71 + 0x11 bytes C++
> > osgTextd.dll!osgText::Font::getStateSet()  Line 97 + 0x19 bytes C++
> > > osgTextd.dll!osgText::Text::Text()  Line 61 + 0xc bytes C++
> > osgtest.exe!UpdateTextOperation::load()  Line 556 + 0x2e bytes C++
> > osgtest.exe!UpdateTextOperation::operator()(osg::Object *
> > callingObject=0x00000000)  Line 499 C++
> > osgd.dll!osg::OperationThread::run()  Line 413 + 0x26 bytes C++
> > OpenThreadsd.dll!OpenThreads::ThreadPrivateActions::StartThread(void *
> > data=0x0174cdb8)  Line 106 + 0xf bytes C++
> > msvcr80d.dll!_callthreadstartex()  Line 348 + 0xf bytes C
> > msvcr80d.dll!_threadstartex(void * ptd=0x0174da48)  Line 331 C
> > kernel32.dll!7c80b683()
> > [Frames below may be incorrect and/or missing, no symbols loaded for
> > kernel32.dll]
> >
> >
> > On 9/2/07, Robert Osfield <robert.osfield at gmail.com> wrote:
> > > Hi Sherman,
> > >
> > > On 9/1/07, sherman wilcox <wilcox.sherman at gmail.com> wrote:
> > > > If I run with --mt 1 it runs for a bit....however if I change that to --mt
> > > > 10 it crashes immediately. Tried this on an old dual-proc and a new
> > > > quad-core system. Here's the stack from the quad-core:
> > > >
> > > > > osgText.dll!osgText::Text::Text()  Line 61 + 0x5 bytes C++
> > > >   osgtest.exe!UpdateTextOperation::load()  Line 556 + 0x24
> > > > bytes C++
> > > >   osgtest.exe!UpdateTextOperation::operator()(osg::Object *
> > > > callingObject=0x00000000)  Line 498 + 0x5 bytes C++
> > > >   osg.dll!osg::OperationThread::run()  Line 416 C++
> > > >
> > > > OpenThreads.dll!OpenThreads::ThreadPrivateActions::StartThread(void
> > > > * data=0x00f7cda8)  Line 120 C++
> > > >   msvcr80.dll!__endthreadex()  + 0x3b bytes
> > > >   msvcr80.dll!__endthreadex ()  + 0xc7 bytes
> > > >   kernel32.dll!@BaseThreadInitThunk at 12()  + 0xe bytes
> > > >   ntdll.dll!__RtlUserThreadStart at 8 ()  + 0x23 bytes
> > > >
> > > > I'm grabbed a copy out of SVN about 30 minutes after you posted. So, I
> > > > believe I have the right code. If you want me to perform any further
> > > > testing/changes just yell.
> > >
> > > Originally I was getting crashes in the Text constructor to the lack
> > > of thread safety on Node,Drawable and StateSet addParent.  This is now
> > > mutexed so "shouldn't" be giving problems.. at least I don't get
> > > problems with it any more.
> > >
> > > I'll test it once again to see if I can knock it over.  Perhaps its a
> > > different problems to the addParent.  Could you try with a debug
> > > version so we can get where abouts within the Text constructor its
> > > crashing.
> > >
> > > Thanks,
> > > Robert.
> > > _______________________________________________
> > > osg-users mailing list
> > > osg-users at lists.openscenegraph.org
> > > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
> > >
> >
> > _______________________________________________
> > osg-users mailing list
> > osg-users at lists.openscenegraph.org
> > http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
> >
> >
> >
> _______________________________________________
> osg-users mailing list
> osg-users at lists.openscenegraph.org
> http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
>



More information about the osg-users mailing list