gwaldron / osgearth

3D Maps for OpenSceneGraph / C++14
https://www.pelicanmapping.com/home-1/opensource
Other
1.51k stars 779 forks source link

Crash with draped layers and picking #640

Closed remoe closed 9 years ago

remoe commented 9 years ago

I had a crash with osgEarth 2.7 and Win64 (release). It has something to do with picking and draped layers? (without removeLayers)

OpenThreads::Atomic::operator++ + 0x5
osgUtil::StateGraph::StateGraph + 0x85
osgUtil::StateGraph::find_or_insert + 0x149
osgUtil::CullVisitor::pushStateSet + 0x29
osgEarth::DrapingCullSet::accept + 0x249
osgUtil::CullVisitor::apply + 0x1864
osg::Camera::accept + 0x109
osgEarth::DrapingTechnique::cullOverlayGroup + 0x514
osgEarth::OverlayDecorator::traverse + 0x351
osgUtil::CullVisitor::apply + 0x118
osg::Group::accept + 0x109
osg::Group::traverse + 0x63
osgUtil::CullVisitor::apply + 0x118
osg::Group::accept + 0x109
osgEarth::GeoLocator::unitToModel + 0x168
osgEarth::MapNode::traverse + 0x656
osgUtil::CullVisitor::apply + 0x118
osg::Group::accept + 0x109
osg::Group::traverse + 0x63
osgUtil::CullVisitor::apply + 0x118
osg::Group::accept + 0x109
osg::Group::traverse + 0x63
osgUtil::CullVisitor::apply + 0x1864
osg::Camera::accept + 0x109
osg::Group::traverse + 0x63
osgUtil::SceneView::cullStage + 0x1401
osgUtil::SceneView::cull + 0x2112
osgViewer::Renderer::cull + 0x430
osgViewer::ViewerBase::renderingTraversals + 0x3441
osgViewer::ViewerBase::frame + 0x112
BaseThreadInitThunk + 0x13
RtlUserThreadStart + 0x33

I'm not sure this is related to #639

gwaldron commented 9 years ago

Thanks Remo. Usually when I see a crash in one of the Atomic operators, a full clean/rebuild solves the problem. Give that a try.

remoe commented 9 years ago

This 2.7 build was a complete rebuild.

gwaldron commented 9 years ago

Does the example function property: osgearth_pick feature_draped_polygons.earth

remoe commented 9 years ago

Yes, this works.

remoe commented 9 years ago

I can reproduce it now with in debug mode with osg 3.2.3:

Unhandled exception at 0x000007FEF4E89170 (ot20-OpenThreadsd.dll) in xx: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
>   ot20-OpenThreadsd.dll!OpenThreads::Atomic::operator++() Line 46 C++
    osg100-osgd.dll!osg::Referenced::ref() Line 173 C++
    osg100-osgUtild.dll!osg::ref_ptr<osg::StateSet const >::ref_ptr<osg::StateSet const >(const osg::StateSet * ptr) Line 31    C++
    osg100-osgUtild.dll!osgUtil::StateGraph::StateGraph(osgUtil::StateGraph * parent, const osg::StateSet * stateset) Line 89   C++
    osg100-osgUtild.dll!osgUtil::StateGraph::find_or_insert(const osg::StateSet * stateset) Line 183    C++
    osg100-osgUtild.dll!osgUtil::CullVisitor::pushStateSet(const osg::StateSet * ss) Line 117   C++
    osgEarthd.dll!osgEarth::DrapingCullSet::accept(osg::NodeVisitor & nv, bool remove) Line 95  C++
    osgEarthd.dll!`anonymous namespace'::DrapingCamera::traverse(osg::NodeVisitor & nv) Line 78 C++
    osg100-osgd.dll!osg::NodeVisitor::traverse(osg::Node & node) Line 194   C++
    osg100-osgUtild.dll!osgUtil::CullVisitor::handle_cull_callbacks_and_traverse(osg::Node & node) Line 314 C++
    osg100-osgUtild.dll!osgUtil::CullVisitor::apply(osg::Camera & camera) Line 1653 C++
    osg100-osgd.dll!osg::Camera::accept(osg::NodeVisitor & nv) Line 54  C++
    osgEarthd.dll!`anonymous namespace'::DrapingCamera::accept(osg::NodeVisitor & nv, const osg::Camera * camera) Line 68   C++
    osgEarthd.dll!osgEarth::DrapingTechnique::cullOverlayGroup(osgEarth::OverlayDecorator::TechRTTParams & params, osgUtil::CullVisitor * cv) Line 589  C++
    osgEarthd.dll!osgEarth::OverlayDecorator::traverse(osg::NodeVisitor & nv) Line 840  C++
    osg100-osgd.dll!osg::NodeVisitor::traverse(osg::Node & node) Line 194   C++
    osg100-osgUtild.dll!osgUtil::CullVisitor::handle_cull_callbacks_and_traverse(osg::Node & node) Line 314 C++

I can reproduce it when I load a map with some layers and picking around and then I load a completely new map. Then it crashes.

remoe commented 9 years ago

Glenn, the main issue is here with an invalid stateset:

void
DrapingCullSet::accept(osg::NodeVisitor& nv, bool remove)
{
    if ( nv.getVisitorType() == nv.CULL_VISITOR )
    {
        osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>( &nv );

        // We will use the visitor's path to prevent doubely-applying the statesets
        // of common ancestors
        const osg::NodePath& nvPath = nv.getNodePath();

        for( std::vector<Entry>::iterator entry = _entries.begin(); entry != _entries.end(); ++entry )
        {
            // If there's an active (non-identity matrix), apply it
            if ( entry->_matrix.valid() )
            {
                entry->_matrix->preMult( *cv->getModelViewMatrix() );
                cv->pushModelViewMatrix( entry->_matrix.get(), osg::Transform::RELATIVE_RF );
            }

            // After pushing the matrix, we can perform the culling bounds test.
            if ( !cv->isCulled( entry->_node->getBound() ) )
            {
                // Apply the statesets in the entry's node path, but skip over the ones that are
                // shared with the current visitor's path since they are already in effect.
                // Count them so we can pop them later.
                int numStateSets = 0;
                for(unsigned i=0; i<entry->_path.size(); ++i)
                {
                    if (i >= nvPath.size() || nvPath[i] != entry->_path[i])
                    {
>>>>>>>>>>>>osg::StateSet* stateSet = entry->_path[i]->getStateSet(); <<<<<<<<<<<<<<<<<<<<<
                        if ( stateSet )
                        {
                            cv->pushStateSet( stateSet );
                            ++numStateSets;
                        }
                    }
                }

Statesets from some paths in entries are sometimes invalid.

jasonbeverage commented 9 years ago

Are you doing your intersection from a separate thread? It sounds like we need to take a reference somewhere that we are not but it would be good to have a small example that shows the issue so we can diagnose what the real issue is.

remoe commented 9 years ago

No I don't do this. Only the database-pager are one of this common threads.

remoe commented 9 years ago

Ok, I've written now a sample to reproduce the crash. It is based on osgearth_pick.cpp. To test you need to do the following:

https://gist.github.com/remoe/4eac7be3efbe9ce64578

change the path of the file to allow load the second earth file here:

https://gist.github.com/remoe/4eac7be3efbe9ce64578#file-osgearth_pick-cpp-L145

gwaldron commented 9 years ago

Pushing a hopeful-fix that uses an observer to keep track of expiring nodes and statesets in the drapeable cullset. Let me know if that works for you.

remoe commented 9 years ago

confirmed! thanks!