Skip to content
GitLab
    • GitLab: the DevOps platform
    • Explore GitLab
    • Install GitLab
    • How GitLab compares
    • Get started
    • GitLab docs
    • GitLab Learn
  • Pricing
  • Talk to an expert
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
    • Switch to GitLab Next
    Projects Groups Topics Snippets
  • Register
  • Sign in
  • openmw openmw
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
    • Locked files
  • Issues 833
    • Issues 833
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 34
    • Merge requests 34
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • OpenMWOpenMW
  • openmwopenmw
  • Issues
  • #4765
Closed
Open
Issue created Dec 24, 2018 by thexyz@thexyz

Data race in ChunkManager -> Array::setBinding

Log:

WARNING: ThreadSanitizer: data race (pid=7927)
  Write of size 4 at 0x7b2800145250 by thread T2:
    #0 osg::Array::setBinding(osg::Array::Binding) /home/xyz/osg/include/osg/Array:189 (libosg.so.160+0x0000004b1174)
    #1 osg::Geometry::setTexCoordArray(unsigned int, osg::Array*, osg::Array::Binding) /home/xyz/osg/src/osg/Geometry.cpp:247 (libosg.so.160+0x0000004a7504)
    #2 osg::Geometry::setTexCoordArray(unsigned int, osg::Array*) /home/xyz/openmw-prefix/include/osg/Geometry:79 (openmw+0x0000016ec485)
    #3 Terrain::ChunkManager::createChunk(float, osg::Vec2f const&, int, unsigned int) /home/xyz/openmw/components/terrain/chunkmanager.cpp:206 (openmw+0x0000018eeef6)
    #4 Terrain::ChunkManager::getChunk(float, osg::Vec2f const&, int, unsigned int) /home/xyz/openmw/components/terrain/chunkmanager.cpp:47 (openmw+0x0000018ed28f)
    #5 Terrain::TerrainGrid::buildTerrain(osg::Group*, float, osg::Vec2f const&) /home/xyz/openmw/components/terrain/terraingrid.cpp:58 (openmw+0x0000018ea0f3)
    #6 Terrain::TerrainGrid::buildTerrain(osg::Group*, float, osg::Vec2f const&) /home/xyz/openmw/components/terrain/terraingrid.cpp:53 (openmw+0x0000018ea07e)
    #7 Terrain::TerrainGrid::buildTerrain(osg::Group*, float, osg::Vec2f const&) /home/xyz/openmw/components/terrain/terraingrid.cpp:50 (openmw+0x0000018e9e90)
    #8 Terrain::TerrainGrid::cacheCell(Terrain::View*, int, int) /home/xyz/openmw/components/terrain/terraingrid.cpp:37 (openmw+0x0000018e9cb5)
    #9 MWWorld::PreloadItem::doWork() /home/xyz/openmw/apps/openmw/mwworld/cellpreloader.cpp:98 (openmw+0x0000014b7598)
    #10 SceneUtil::WorkThread::run() /home/xyz/openmw/components/sceneutil/workqueue.cpp:134 (openmw+0x00000172c74e)
    #11 OpenThreads::ThreadPrivateActions::StartThread(void*) <null> (libOpenThreads.so.21+0x00000000a2ba)
    #12 <null> <null> (libtsan.so.0+0x00000002583b)

  Previous write of size 4 at 0x7b2800145250 by thread T13:
    #0 osg::Array::setBinding(osg::Array::Binding) /home/xyz/osg/include/osg/Array:189 (libosg.so.160+0x0000004b1174)
    #1 osg::Geometry::setTexCoordArray(unsigned int, osg::Array*, osg::Array::Binding) /home/xyz/osg/src/osg/Geometry.cpp:247 (libosg.so.160+0x0000004a7504)
    #2 osg::Geometry::setTexCoordArray(unsigned int, osg::Array*) /home/xyz/openmw-prefix/include/osg/Geometry:79 (openmw+0x0000016ec485)
    #3 Terrain::ChunkManager::createChunk(float, osg::Vec2f const&, int, unsigned int) /home/xyz/openmw/components/terrain/chunkmanager.cpp:206 (openmw+0x0000018eeef6)
    #4 Terrain::ChunkManager::getChunk(float, osg::Vec2f const&, int, unsigned int) /home/xyz/openmw/components/terrain/chunkmanager.cpp:47 (openmw+0x0000018ed28f)
    #5 Terrain::TerrainGrid::buildTerrain(osg::Group*, float, osg::Vec2f const&) /home/xyz/openmw/components/terrain/terraingrid.cpp:58 (openmw+0x0000018ea0f3)
    #6 Terrain::TerrainGrid::buildTerrain(osg::Group*, float, osg::Vec2f const&) /home/xyz/openmw/components/terrain/terraingrid.cpp:50 (openmw+0x0000018e9e90)
    #7 Terrain::TerrainGrid::buildTerrain(osg::Group*, float, osg::Vec2f const&) /home/xyz/openmw/components/terrain/terraingrid.cpp:51 (openmw+0x0000018e9f31)
    #8 Terrain::TerrainGrid::cacheCell(Terrain::View*, int, int) /home/xyz/openmw/components/terrain/terraingrid.cpp:37 (openmw+0x0000018e9cb5)
    #9 MWWorld::PreloadItem::doWork() /home/xyz/openmw/apps/openmw/mwworld/cellpreloader.cpp:98 (openmw+0x0000014b7598)
    #10 SceneUtil::WorkThread::run() /home/xyz/openmw/components/sceneutil/workqueue.cpp:134 (openmw+0x00000172c74e)
    #11 OpenThreads::ThreadPrivateActions::StartThread(void*) <null> (libOpenThreads.so.21+0x00000000a2ba)
    #12 <null> <null> (libtsan.so.0+0x00000002583b)

  Location is heap block of size 152 at 0x7b28001451e0 allocated by thread T4:
    #0 operator new(unsigned long) <null> (libtsan.so.0+0x00000006f546)
    #1 Terrain::BufferCache::getUVBuffer(unsigned int) /home/xyz/openmw/components/terrain/buffercache.cpp:191 (openmw+0x0000019c318d)
    #2 Terrain::ChunkManager::createChunk(float, osg::Vec2f const&, int, unsigned int) /home/xyz/openmw/components/terrain/chunkmanager.cpp:206 (openmw+0x0000018eeed7)
    #3 Terrain::ChunkManager::getChunk(float, osg::Vec2f const&, int, unsigned int) /home/xyz/openmw/components/terrain/chunkmanager.cpp:47 (openmw+0x0000018ed28f)
    #4 Terrain::TerrainGrid::buildTerrain(osg::Group*, float, osg::Vec2f const&) /home/xyz/openmw/components/terrain/terraingrid.cpp:58 (openmw+0x0000018ea0f3)
    #5 Terrain::TerrainGrid::buildTerrain(osg::Group*, float, osg::Vec2f const&) /home/xyz/openmw/components/terrain/terraingrid.cpp:50 (openmw+0x0000018e9e90)
    #6 Terrain::TerrainGrid::buildTerrain(osg::Group*, float, osg::Vec2f const&) /home/xyz/openmw/components/terrain/terraingrid.cpp:50 (openmw+0x0000018e9e90)
    #7 Terrain::TerrainGrid::cacheCell(Terrain::View*, int, int) /home/xyz/openmw/components/terrain/terraingrid.cpp:37 (openmw+0x0000018e9cb5)
    #8 MWWorld::PreloadItem::doWork() /home/xyz/openmw/apps/openmw/mwworld/cellpreloader.cpp:98 (openmw+0x0000014b7598)
    #9 SceneUtil::WorkThread::run() /home/xyz/openmw/components/sceneutil/workqueue.cpp:134 (openmw+0x00000172c74e)
    #10 OpenThreads::ThreadPrivateActions::StartThread(void*) <null> (libOpenThreads.so.21+0x00000000a2ba)
    #11 <null> <null> (libtsan.so.0+0x00000002583b)

  Thread T2 (tid=8026, running) created by main thread at:
    #0 pthread_create <null> (libtsan.so.0+0x000000028e53)
    #1 OpenThreads::Thread::start() /home/xyz/osg/src/OpenThreads/pthreads/PThread.cpp:671 (libOpenThreads.so.21+0x000000008e1c)
    #2 OpenThreads::Thread::startThread() /home/xyz/osg/src/OpenThreads/pthreads/PThread.cpp:694 (libOpenThreads.so.21+0x000000008ec9)
    #3 SceneUtil::WorkQueue::WorkQueue(int) /home/xyz/openmw/components/sceneutil/workqueue.cpp:49 (openmw+0x00000172bf37)
    #4 OMW::Engine::prepareEngine(Settings::Manager&) /home/xyz/openmw/apps/openmw/engine.cpp:469 (openmw+0x00000166d6a3)
    #5 OMW::Engine::go() /home/xyz/openmw/apps/openmw/engine.cpp:663 (openmw+0x00000166f5dc)
    #6 runApplication(int, char**) /home/xyz/openmw/apps/openmw/main.cpp:252 (openmw+0x00000164e5a2)
    #7 wrapApplication(int (*)(int, char**), int, char**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/xyz/openmw/components/debug/debugging.cpp:135 (openmw+0x00000186e9b3)
    #8 main /home/xyz/openmw/apps/openmw/main.cpp:264 (openmw+0x00000164e69b)

  Thread T13 (tid=8037, running) created by main thread at:
    #0 pthread_create <null> (libtsan.so.0+0x000000028e53)
    #1 OpenThreads::Thread::start() /home/xyz/osg/src/OpenThreads/pthreads/PThread.cpp:671 (libOpenThreads.so.21+0x000000008e1c)
    #2 OpenThreads::Thread::startThread() /home/xyz/osg/src/OpenThreads/pthreads/PThread.cpp:694 (libOpenThreads.so.21+0x000000008ec9)
    #3 SceneUtil::WorkQueue::WorkQueue(int) /home/xyz/openmw/components/sceneutil/workqueue.cpp:49 (openmw+0x00000172bf37)
    #4 OMW::Engine::prepareEngine(Settings::Manager&) /home/xyz/openmw/apps/openmw/engine.cpp:469 (openmw+0x00000166d6a3)
    #5 OMW::Engine::go() /home/xyz/openmw/apps/openmw/engine.cpp:663 (openmw+0x00000166f5dc)
    #6 runApplication(int, char**) /home/xyz/openmw/apps/openmw/main.cpp:252 (openmw+0x00000164e5a2)
    #7 wrapApplication(int (*)(int, char**), int, char**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/xyz/openmw/components/debug/debugging.cpp:135 (openmw+0x00000186e9b3)
    #8 main /home/xyz/openmw/apps/openmw/main.cpp:264 (openmw+0x00000164e69b)

  Thread T4 (tid=8028, running) created by main thread at:
    #0 pthread_create <null> (libtsan.so.0+0x000000028e53)
    #1 OpenThreads::Thread::start() /home/xyz/osg/src/OpenThreads/pthreads/PThread.cpp:671 (libOpenThreads.so.21+0x000000008e1c)
    #2 OpenThreads::Thread::startThread() /home/xyz/osg/src/OpenThreads/pthreads/PThread.cpp:694 (libOpenThreads.so.21+0x000000008ec9)
    #3 SceneUtil::WorkQueue::WorkQueue(int) /home/xyz/openmw/components/sceneutil/workqueue.cpp:49 (openmw+0x00000172bf37)
    #4 OMW::Engine::prepareEngine(Settings::Manager&) /home/xyz/openmw/apps/openmw/engine.cpp:469 (openmw+0x00000166d6a3)
    #5 OMW::Engine::go() /home/xyz/openmw/apps/openmw/engine.cpp:663 (openmw+0x00000166f5dc)
    #6 runApplication(int, char**) /home/xyz/openmw/apps/openmw/main.cpp:252 (openmw+0x00000164e5a2)
    #7 wrapApplication(int (*)(int, char**), int, char**, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/xyz/openmw/components/debug/debugging.cpp:135 (openmw+0x00000186e9b3)
    #8 main /home/xyz/openmw/apps/openmw/main.cpp:264 (openmw+0x00000164e69b)

SUMMARY: ThreadSanitizer: data race /home/xyz/osg/include/osg/Array:189 in osg::Array::setBinding(osg::Array::Binding)

ChunkManager::createChunk is called by multiple threads on the same ChunkManager object. Inside, it uses mBufferCache.getUVBuffer(numVerts).

If multiple threads get same numVerts they will retrieve the same osg::Vec2Array object from the BufferCache. On the first look this appears to be safe since the threads aren't writing to the buffer.

However, when the buffer passed in geometry->setTexCoordArray, OSG will call setBinding on the (shared) Array object here: https://github.com/OpenMW/osg/blob/ecedf3232c2f1b3b6a2f06f77ea37a9afb6a93f5/src/osg/Geometry.cpp#L247

setBinding will assign to _binding field of the Array object from multiple threads at the same time, resulting in a data race.

Assignee
Assign to
Time tracking