Skip to content

Freeze in CompositeMapRenderer::drawImplementation

A loop to compile composite maps might become infinite if timeLeft is not properly modified. It's modified in the compile function but there are multiple early returns which means in some cases it is not. And also it means the map is not compiled so they are removed from mCompileSet and put back while timeLeft has constant non zero value.

From Discord https://discord.com/channels/260439894298460160/260443579908882434/1175407523621245042:

(lldb) thread select 3
* thread #3, name = 'openmw'
    frame #0: 0x0000555557eb2d57 openmw`std::_Rb_tree<osg::ref_ptr<Terrain::CompositeMap>, osg::ref_ptr<Terrain::CompositeMap>, std::_Identity<osg::ref_ptr<Terrain::CompositeMap>>, std::less<osg::ref_ptr<Terrain::CompositeMap>>, std::allocator<osg::ref_ptr<Terrain::CompositeMap>>>::equal_range(this=0x000055555be36ca8, __k=0x00007fffdd95d098) at stl_tree.h:2037:5
   2034		}
   2035	     return pair<iterator, iterator>(iterator(__y),
   2036					     iterator(__y));
-> 2037	   }
   2038	
   2039	 template<typename _Key, typename _Val, typename _KeyOfValue,
   2040		  typename _Compare, typename _Alloc>
(lldb) bt
* thread #3, name = 'openmw'
  * frame #0: 0x0000555557eb2d57 openmw`std::_Rb_tree<osg::ref_ptr<Terrain::CompositeMap>, osg::ref_ptr<Terrain::CompositeMap>, std::_Identity<osg::ref_ptr<Terrain::CompositeMap>>, std::less<osg::ref_ptr<Terrain::CompositeMap>>, std::allocator<osg::ref_ptr<Terrain::CompositeMap>>>::equal_range(this=0x000055555be36ca8, __k=0x00007fffdd95d098) at stl_tree.h:2037:5
    frame #1: 0x0000555557eb2b3e openmw`std::_Rb_tree<osg::ref_ptr<Terrain::CompositeMap>, osg::ref_ptr<Terrain::CompositeMap>, std::_Identity<osg::ref_ptr<Terrain::CompositeMap>>, std::less<osg::ref_ptr<Terrain::CompositeMap>>, std::allocator<osg::ref_ptr<Terrain::CompositeMap>>>::erase(this=0x000055555be36ca8, __x=0x00007fffdd95d098) at stl_tree.h:2519:38
    frame #2: 0x0000555557eb1f1d openmw`std::set<osg::ref_ptr<Terrain::CompositeMap>, std::less<osg::ref_ptr<Terrain::CompositeMap>>, std::allocator<osg::ref_ptr<Terrain::CompositeMap>>>::erase(this=size=1, __x=0x00007fffdd95d098) at stl_set.h:687:21
    frame #3: 0x0000555557eb0e1a openmw`Terrain::CompositeMapRenderer::drawImplementation(this=0x000055555be36b30, renderInfo=0x00007fffdd95d450) const at compositemaprenderer.cpp:55:25
    frame #4: 0x00007ffff7f3d8ff libosgParticled.so.162`osg::Drawable::drawInner(this=0x000055555be36b30, renderInfo=0x00007fffdd95d450) const at Drawable:276:35
    frame #5: 0x00007ffff7f3dc02 libosgParticled.so.162`osg::Drawable::draw(this=0x000055555be36b30, renderInfo=0x00007fffdd95d450) const at Drawable:617:18
    frame #6: 0x00007ffff70d3b7c libosgUtild.so.162`osgUtil::RenderLeaf::render(this=0x000055555fbc4ff0, renderInfo=0x00007fffdd95d450, previous=0x0000000000000000) at RenderLeaf.cpp:81:24
    frame #7: 0x00007ffff70c6c78 libosgUtild.so.162`osgUtil::RenderBin::drawImplementation(this=0x000055555fbc4c70, renderInfo=0x00007fffdd95d450, previous=0x00007fffdd95d530) at RenderBin.cpp:487:27
    frame #8: 0x00007ffff70da2a1 libosgUtild.so.162`osgUtil::RenderStage::drawImplementation(this=0x000055555fbc4c70, renderInfo=0x00007fffdd95d450, previous=0x00007fffdd95d530) at RenderStage.cpp:1404:34
    frame #9: 0x00007ffff70c69e0 libosgUtild.so.162`osgUtil::RenderBin::draw(this=0x000055555fbc4c70, renderInfo=0x00007fffdd95d450, previous=0x00007fffdd95d530) at RenderBin.cpp:430:28
    frame #10: 0x00007ffff70d8771 libosgUtild.so.162`osgUtil::RenderStage::drawInner(this=0x000055555fbc4c70, renderInfo=0x00007fffdd95d450, previous=0x00007fffdd95d530, doCopyTexture=0x00007fffdd95d413) at RenderStage.cpp:929:20
    frame #11: 0x00007ffff70d9a4d libosgUtild.so.162`osgUtil::RenderStage::draw(this=0x000055555fbc4c70, renderInfo=0x00005555595c1a98, previous=0x00007fffdd95d530) at RenderStage.cpp:1240:18
    frame #12: 0x00007ffff70d5845 libosgUtild.so.162`osgUtil::RenderStage::drawPreRenderStages(this=0x00005555595f1ab0, renderInfo=0x00005555595c1a98, previous=0x00007fffdd95d530) at RenderStage.cpp:222:26
    frame #13: 0x00007ffff70ec75d libosgUtild.so.162`osgUtil::SceneView::draw(this=0x00005555595c1a00) at SceneView.cpp:1426:42
    frame #14: 0x00007ffff7d67914 libosgViewerd.so.162`osgViewer::Renderer::draw(this=0x00005555595b5350) at Renderer.cpp:797:28
    frame #15: 0x00007ffff7d68c62 libosgViewerd.so.162`osgViewer::Renderer::operator()(this=0x00005555595b5350, (null)=0x0000555559696500) at Renderer.cpp:952:13
    frame #16: 0x00007ffff683c28b libosgd.so.162`osg::GraphicsContext::runOperations(this=0x0000555559696500) at GraphicsContext.cpp:696:62
    frame #17: 0x00007ffff6845d2f libosgd.so.162`osg::RunOperations::operator()(this=0x0000555559a37120, context=0x0000555559696500) at GraphicsThread.cpp:139:27
    frame #18: 0x00007ffff6845554 libosgd.so.162`osg::GraphicsOperation::operator()(this=0x0000555559a37120, object=0x0000555559696500) at GraphicsThread.cpp:53:29
    frame #19: 0x00007ffff68bb159 libosgd.so.162`osg::OperationThread::run(this=0x0000555559a36e90) at OperationThread.cpp:438:25
    frame #20: 0x00007ffff68454b8 libosgd.so.162`osg::GraphicsThread::run(this=0x0000555559a36e90) at GraphicsThread.cpp:38:25
    frame #21: 0x00007ffff7e58cb5 libOpenThreadsd.so.21`OpenThreads::ThreadPrivateActions::StartThread(data=0x0000555559a36e90) at PThread.cpp:221:20
    frame #22: 0x00007ffff10aa9eb libc.so.6`___lldb_unnamed_symbol3598 + 731
    frame #23: 0x00007ffff112e7cc libc.so.6`___lldb_unnamed_symbol4045 + 7

Instead the deadline should be calculated at the beginning of the loop and used to mark the end of it:

const auto deadline = std::chrono::steady_clock::now() + std::chrono::duration<double>(availableTime);
while (!mCompileSet.empty() && std::chrono::steady_clock::now() < deadline)
{
    // <...>
}