Threading issue with NonOrientedGeometryCursor on the same Hyper Tree
When creating multiple NonOrientedGeometry cursors on the same hypertree, VTK crashes.
Minimal code to reproduce (compile VTK with SMP backend set to StdThread) :
#include <vtkNew.h>
#include <vtkRandomHyperTreeGridSource.h>
#include <vtkHyperTreeGrid.h>
#include <vtkHyperTree.h>
#include <vtkSMPTools.h>
#include <vtkHyperTreeGridNonOrientedGeometryCursor.h>
template<typename T>
void RecursivePass(T* cursor)
{
volatile const double* origin = cursor->GetOrigin();
if (!cursor->IsLeaf())
{
int numChildren = cursor->GetNumberOfChildren();
for (unsigned char child = 0u; child < numChildren; ++child)
{
cursor->ToChild(child);
RecursivePass(cursor);
cursor->ToParent();
}
}
}
int main(int, char*[])
{
vtkNew<vtkRandomHyperTreeGridSource> source;
source->SetDimensions(5, 5, 5);
source->SetSeed(42);
source->SetSplitFraction(0.6);
source->Update();
vtkHyperTreeGrid* htg = source->GetHyperTreeGridOutput();
// We just make sure that we have a number af levels and leafes to explore
vtkIdType treeIndex = 0;
vtkHyperTree* tree = htg->GetTree(treeIndex);
while (tree->GetNumberOfLevels() < 5 && tree->GetNumberOfLeaves() < 5000 && treeIndex < htg->GetMaxNumberOfTrees())
{
tree = htg->GetTree(treeIndex);
}
vtkSMPTools::For(0, 1000, [treeIndex, htg](vtkIdType begin, vtkIdType end) {
vtkNew<vtkHyperTreeGridNonOrientedGeometryCursor> cursor;
for (vtkIdType i = begin; i < end; ++i)
{
htg->InitializeNonOrientedGeometryCursor(cursor, treeIndex, false);
RecursivePass(cursor.Get());
}
});
return 0;
}
gdb backtrace :
#0 0x00007ffff2761880 in vtkHyperTreeGridScales::Update (this=0x5555555c7740, level=5) at /home/timothee/Dev/Paraview/paraview/VTK/Common/DataModel/vtkHyperTreeGridScales.h:128
#1 0x00007ffff276145f in vtkHyperTreeGridScales::GetScale (this=0x5555555c7740, level=5) at /home/timothee/Dev/Paraview/paraview/VTK/Common/DataModel/vtkHyperTreeGridScales.h:61
#2 0x00007ffff278c247 in vtkHyperTreeGridNonOrientedGeometryCursor::ToChild (this=0x7fffcc000b70, ichild=0 '\000')
at /home/timothee/Dev/Paraview/paraview/VTK/Common/DataModel/vtkHyperTreeGridNonOrientedGeometryCursor.cxx:245
#3 0x000055555555aba8 in void RecursivePass<vtkHyperTreeGridNonOrientedGeometryCursor>(vtkHyperTreeGridNonOrientedGeometryCursor*) ()
#4 0x000055555555abb4 in void RecursivePass<vtkHyperTreeGridNonOrientedGeometryCursor>(vtkHyperTreeGridNonOrientedGeometryCursor*) ()
#5 0x000055555555abb4 in void RecursivePass<vtkHyperTreeGridNonOrientedGeometryCursor>(vtkHyperTreeGridNonOrientedGeometryCursor*) ()
#6 0x000055555555abb4 in void RecursivePass<vtkHyperTreeGridNonOrientedGeometryCursor>(vtkHyperTreeGridNonOrientedGeometryCursor*) ()
#7 0x000055555555abb4 in void RecursivePass<vtkHyperTreeGridNonOrientedGeometryCursor>(vtkHyperTreeGridNonOrientedGeometryCursor*) ()
#8 0x0000555555559338 in main::{lambda(long long, long long)#1}::operator()(long long, long long) const ()
[...]
Note that when removing the line
volatile const double* origin = cursor->GetOrigin();
the program can still crash but the backtrace is just composed of libc calls.