Data race in vtkAlgorithm triggered by vtkImageAppend
This issue was created automatically from an original Mantis Issue. Further discussion may take place here.
I just spent several hours tracking down a mysterious crash, which appears to be due to an insidious race condition triggered when running a multi-threaded vtkImageAppend filter.
The crux of the problem is that vtkImageAppend::ThreadedRequestData() indirectly calls vtkAlgorithm::GetOutputPort() which, despite outward appearances is not thread-safe.
I found this race by running helgrind (a valgrind tool) on our application - which spits out the following (threads 8 and 9 are the algorithm's worker threads):
==4282== Possible data race during read of size 8 at 0x2c3f0c20 by thread #9 (closed) ==4282== at 0xFBF50C: vtkSmartPointer::operator vtkAlgorithmOutput*() const (vtkSmartPointer.h:75) ==4282== by 0xFBE287: vtkAlgorithm::GetOutputPort(int) (vtkAlgorithm.cxx:1218) ==4282== by 0xFF4712: vtkExecutive::GetProducerPort(vtkDataObject*) (vtkExecutive.cxx:419) ==4282== by 0xFDD976: vtkDataObject::GetProducerPort() (vtkDataObject.cxx:362) ==4282== by 0x101C4DC: vtkImageData::GetScalarType() (vtkImageData.cxx:1498) ==4282== by 0x101C94F: vtkImageData::GetScalarSize() (vtkImageData.cxx:1579) ==4282== by 0xF42F2D: vtkImageAppend::InitOutput(int*, vtkImageData*) (vtkImageAppend.cxx:427) ==4282== by 0xF430CA: vtkImageAppend::ThreadedRequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*, vtkImageData***, vtkImageData**, int*, int) (vtkImageAppend.cxx:476) ==4282== by 0x10C2714: vtkThreadedImageAlgorithmThreadedExecute(void*) (vtkThreadedImageAlgorithm.cxx:202) ==4282== by 0x4C29D69: mythread_wrapper (hg_intercepts.c:221) ==4282== by 0x9C4CD8B: start_thread (pthread_create.c:304) ==4282== by 0xB74104C: clone (clone.S:112) ==4282== This conflicts with a previous write of size 8 by thread #8 ==4282== at 0x1255D7A: vtkSmartPointerBase::Swap(vtkSmartPointerBase&) (vtkSmartPointerBase.cxx:105) ==4282== by 0x1255CF8: vtkSmartPointerBase::operator=(vtkSmartPointerBase const&) (vtkSmartPointerBase.cxx:88) ==4282== by 0xFBF162: vtkSmartPointer::operator=(vtkSmartPointer const&) (vtkSmartPointer.h:27) ==4282== by 0xFBE2C9: vtkAlgorithm::GetOutputPort(int) (vtkAlgorithm.cxx:1221) ==4282== by 0xFF4712: vtkExecutive::GetProducerPort(vtkDataObject*) (vtkExecutive.cxx:419) ==4282== by 0xFDD976: vtkDataObject::GetProducerPort() (vtkDataObject.cxx:362) ==4282== by 0x101C4DC: vtkImageData::GetScalarType() (vtkImageData.cxx:1498) ==4282== by 0x101C94F: vtkImageData::GetScalarSize() (vtkImageData.cxx:1579) ==4282== Address 0x2c3f0c20 is 0 bytes inside a block of size 8 alloc'd ==4282== at 0x4C28B82: operator new(unsigned long) (vg_replace_malloc.c:261) ==4282== by 0xFC0BB3: __gnu_cxx::new_allocator<vtkSmartPointer >::allocate(unsigned long, void const*) (new_allocator.h:89) ==4282== by 0xFC0948: std::_Vector_base<vtkSmartPointer, std::allocator<vtkSmartPointer > >::_M_allocate(unsigned long) (in /home/ben/Dev/virat2-superbuild-debug/TPL/VisGUI/bin/viqui) ==4282== by 0xFC02C3: std::vector<vtkSmartPointer, std::allocator<vtkSmartPointer > >::_M_fill_insert(__gnu_cxx::__normal_iterator<vtkSmartPointer*, std::vector<vtkSmartPointer, std::allocator<vtkSmartPointer > > >, unsigned long, vtkSmartPointer const&) (vector.tcc:414) ==4282== by 0xFBFBED: std::vector<vtkSmartPointer, std::allocator<vtkSmartPointer > >::insert(__gnu_cxx::__normal_iterator<vtkSmartPointer*, std::vector<vtkSmartPointer, std::allocator<vtkSmartPointer > > >, unsigned long, vtkSmartPointer const&) (stl_vector.h:859) ==4282== by 0xFBF4A4: std::vector<vtkSmartPointer, std::allocator<vtkSmartPointer > >::resize(unsigned long, vtkSmartPointer) (stl_vector.h:558) ==4282== by 0xFBC7D8: vtkAlgorithm::SetNumberOfOutputPorts(int) (vtkAlgorithm.cxx:772) ==4282== by 0x1014A64: vtkImageAlgorithm::vtkImageAlgorithm() (vtkImageAlgorithm.cxx:32) ==4282== by 0x10C1BE4: vtkThreadedImageAlgorithm::vtkThreadedImageAlgorithm() (vtkThreadedImageAlgorithm.cxx:31) ==4282== by 0xF420D9: vtkImageAppend::vtkImageAppend() (vtkImageAppend.cxx:31) ==4282== by 0xF42093: vtkImageAppend::New() (vtkImageAppend.cxx:28)