[osg-users] DatabasePager::DatabaseThread is crashing when DatabasePager has been deleted

Hartwig Wiesmann hartwig.wiesmann at skywind.eu
Sun Mar 25 02:28:52 PDT 2018


Hi Robert,

sorry, that it was not clear enough. What I tried to explain is in summary that the database pager starts twice as many threads as it should but keeps track of only half of them. Therefore, when the viewer is closed the database pager only cancels half of them while the other half is still running. And the still running threads then access via the "_pager" pointer the non-existing database pager.

This is what happens in details and what I tried to explain by pasting the relevant code previously:
The database pager keeps track of the running threads in "_databaseThreads". When setting up "_databaseThreads" (currently empty) in requestNodeFile the threads are immediately created and started (in "setUpThreads"). To be precise, the threads are actually started in Thread::start() which is called from "setUpThreads".
At this moment N threads have been created, started and are tracked in "_databaseThreads".
Afterwards, the mentioned for-loop starts again(!) N threads but uses the same list (namely "_databaseThreads") to track them. Therefore, from the now running 2*N threads N are running untracked.

This can also be seen when looking with a debugger at the number of threads the database pager has been generated.

This bug can be solved by

a) moving the "_startThreadCalled" assignment further down

Code:
            _done = false;
            OSG_INFO<<"DatabasePager::startThread()"<<std::endl;

            if (_databaseThreads.empty())
            {
                setUpThreads(
                    osg::DisplaySettings::instance()->getNumOfDatabaseThreadsHint(),
                    osg::DisplaySettings::instance()->getNumOfHttpDatabaseThreadsHint());
            }

					for(DatabaseThreadList::const_iterator dt_itr = _databaseThreads.begin();
                dt_itr != _databaseThreads.end();
                ++dt_itr)
            {
                (*dt_itr)->startThread();
            }
            _startThreadCalled = true;




or 

b) inserting an else-statement to start either only newly added or the already existing threads


Code:
            _startThreadCalled = true;
            _done = false;
            OSG_INFO<<"DatabasePager::startThread()"<<std::endl;

            if (_databaseThreads.empty())
            {
                setUpThreads(
                    osg::DisplaySettings::instance()->getNumOfDatabaseThreadsHint(),
                    osg::DisplaySettings::instance()->getNumOfHttpDatabaseThreadsHint());
            }
					else
					for(DatabaseThreadList::const_iterator dt_itr = _databaseThreads.begin();
                dt_itr != _databaseThreads.end();
                ++dt_itr)
            {
                (*dt_itr)->startThread();
            }




Which solution is chosen is a matter of taste.

I also recommend to document the functionality of "_startThreadCalled" because the wrong usage (or better hidden effects) of this flag in the above mentioned code causes the bug.

I can provide a patch but I first would like to make sure that my analysis are correct (I think so but I am not an expert).

Cheers,
Hartwig

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=73164#73164







More information about the osg-users mailing list