Hi,
I noticed crashing in dotosg wrappers when try to use osgDB::readNodeFile from
multiple threads.
Crash occurs when I try to load .osg file from two threads.
For example callstack of crashed thread:
osg80_osgDB!concrete_wrapper::matches+0x4
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readObjectOfType+0x527
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readObjectOfType+0x28
osgdb_deprecated_osg!Drawable_readLocalData+0xa1
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readObject+0x8fb
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readDrawable+0xe1
osgdb_deprecated_osg!Geode_readLocalData+0x90
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readObject+0x8fb
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readNode+0xe1
osgdb_deprecated_osg!Group_readLocalData+0x71
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readObject+0x8fb
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readNode+0xe1
osgdb_deprecated_osg!Group_readLocalData+0x71
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readObject+0x8fb
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readNode+0xe1
osgdb_osg!OSGReaderWriter::readNode+0xfe
osgdb_osg!OSGReaderWriter::readNode+0x31c
osg80_osgDB!osgDB::Registry::ReadNodeFunctor::doRead+0x28
osg80_osgDB!osgDB::Registry::read+0x5e4
osg80_osgDB!osgDB::Registry::readImplementation+0x34c
osg80_osgDB!osgDB::Registry::readNodeImplementation+0x6a
osg80_osgDB!osgDB::Registry::readNode+0xfc
osg80_osgDB!osgDB::readNodeFile+0x4e
[...]
second thread callstack:
msvcp90!std::basic_istream<char,std::char_traits<char>
msvcp90!std::basic_istream<char,std::char_traits<char>
osg80_osgDB!osgDB::FieldReader::_readField+0x3f8
osg80_osgDB!osgDB::FieldReaderIterator::field+0x19d
osgdb_deprecated_osg!Array_readLocalData+0xbfb
osgdb_deprecated_osg!Geometry_readLocalData+0x991
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readObject+0x8fb
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readDrawable+0xe1
osgdb_deprecated_osg!Geode_readLocalData+0x90
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readObject+0x8fb
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readNode+0xe1
osgdb_deprecated_osg!Group_readLocalData+0x71
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readObject+0x8fb
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readNode+0xe1
osgdb_deprecated_osg!Group_readLocalData+0x9a
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readObject+0x8fb
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readNode+0xe1
osgdb_deprecated_osg!Group_readLocalData+0x9a
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readObject+0x8fb
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readNode+0xe1
osgdb_deprecated_osg!Group_readLocalData+0x71
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readObject+0x8fb
osg80_osgDB!osgDB::DeprecatedDotOsgWrapperManager::readNode+0xe1
osgdb_osg!OSGReaderWriter::readNode+0xfe
osgdb_osg!OSGReaderWriter::readNode+0x31c
osg80_osgDB!osgDB::Registry::ReadNodeFunctor::doRead+0x28
osg80_osgDB!osgDB::Registry::read+0x5e4
osg80_osgDB!osgDB::Registry::readImplementation+0x34c
osg80_osgDB!osgDB::Registry::readNodeImplementation+0x6a
osg80_osgDB!osgDB::Registry::readNode+0xfc
osg80_osgDB!osgDB::readNodeFile+0x4e
[...]
code:
struct concrete_wrapper: basic_type_wrapper
{
virtual ~concrete_wrapper() {}
concrete_wrapper(const osg::Object *myobj) : myobj_(myobj) {}
bool matches(const osg::Object *proto) const
{
return myobj_->isSameKindAs(proto); <<<<<<<<<<<<<<<<<CRASH HERE<<<<<<<
}
const osg::Object *myobj_;
};
crash occurs because myobj_ is NULL.
myobj_ passed from osgdb_deprecated_osg!Drawable_readLocalData as s_drawstate
bool Drawable_readLocalData(Object& obj, Input& fr)
{
bool iteratorAdvanced = false;
Drawable& drawable = static_cast<Drawable&>(obj);
static ref_ptr<StateSet> s_drawstate = new osg::StateSet;
if (StateSet* readState =
static_cast<StateSet*>(fr.readObjectOfType(*s_drawstate)))
{
drawable.setStateSet(readState);
iteratorAdvanced = true;
}
[...]
so problem is in
static ref_ptr<StateSet> s_drawstate = new osg::StateSet;
MSVC 2008 x64 compiler (maybe gcc too) generate this code as:
static bool s_drawstate_init = false;
static ref_ptr<StateSet> s_drawstate = NULL;
bool Drawable_readLocalData(Object& obj, Input& fr)
{
bool iteratorAdvanced = false;
Drawable& drawable = static_cast<Drawable&>(obj);
if(!s_drawstate_init)
{
s_drawstate_init = true;
s_drawstate = new osg::StateSet;
}
if (StateSet* readState =
static_cast<StateSet*>(fr.readObjectOfType(*s_drawstate)))
{
drawable.setStateSet(readState);
iteratorAdvanced = true;
}
[...]
and this code is not thread safe as you can see.
Possible solution is to move static variables to global scope to avoid lazy
initialization.
Mikhail.
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org