Skip to content

Commit b8bcf5e

Browse files
committed
Merge pull request #277 from andrewkaufman/rootAttrCrash
Fixing seg fault when attempting to read a non-existant attribute several times
2 parents 34416ae + 9f05a15 commit b8bcf5e

File tree

2 files changed

+52
-36
lines changed

2 files changed

+52
-36
lines changed

src/IECore/SceneCache.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ class SceneCache::ReaderImplementation : public SceneCache::Implementation
535535
}
536536
if ( !it.first->second )
537537
{
538+
m_attributeSampleTimes.erase( it.first );
538539
throw Exception( ( boost::format( "No samples for attribute %s available" ) % name.value() ).str() );
539540
}
540541
return *(it.first->second);

test/IECore/SceneCacheThreadingTest.cpp

Lines changed: 51 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,11 @@
3434

3535
#include <vector>
3636
#include <iostream>
37+
3738
#include "tbb/tbb.h"
39+
3840
#include "IECore/SharedSceneInterfaces.h"
41+
3942
#include "SceneCacheThreadingTest.h"
4043

4144
using namespace boost;
@@ -52,61 +55,72 @@ struct SceneCacheThreadingTest
5255
{
5356
public :
5457

55-
TestSceneCache() : m_errors( 0 )
58+
TestSceneCache( const char *attribute ) : m_errors( 0 ), m_attribute( attribute )
5659
{
5760
}
58-
59-
void operator() ( int instance ) const
61+
62+
TestSceneCache( TestSceneCache &that, tbb::split ) : m_errors( 0 ), m_attribute( that.m_attribute )
6063
{
61-
for ( size_t i = 0; i < 1000; i++ )
64+
}
65+
66+
void operator()( const blocked_range<size_t> &r ) const
67+
{
68+
for ( size_t i = r.begin(); i != r.end(); ++i )
6269
{
63-
if ( (instance + i) % 7 == 0 )
64-
{
65-
SharedSceneInterfaces::clear();
66-
}
67-
ConstSceneInterfacePtr scene = SharedSceneInterfaces::get("test/IECore/data/sccFiles/attributeAtRoot.scc");
68-
try
70+
for ( size_t j = 0; j < 1000; j++ )
6971
{
70-
scene->readAttribute("w", 0);
71-
}
72-
catch( Exception e )
73-
{
74-
m_errors++;
72+
if ( ( i + j ) % 7 == 0 )
73+
{
74+
SharedSceneInterfaces::clear();
75+
}
76+
77+
ConstSceneInterfacePtr scene = SharedSceneInterfaces::get("test/IECore/data/sccFiles/attributeAtRoot.scc");
78+
79+
try
80+
{
81+
scene->readAttribute( m_attribute, 0 );
82+
}
83+
catch( Exception &e )
84+
{
85+
m_errors++;
86+
}
7587
}
7688
}
7789
}
78-
90+
91+
void join( const TestSceneCache &that )
92+
{
93+
m_errors += that.m_errors;
94+
}
95+
7996
size_t errors() const
8097
{
8198
return m_errors;
8299
}
83100

84101
private :
85102
mutable size_t m_errors;
86-
SceneInterface::Path m_attributePath;
103+
SceneInterface::Name m_attribute;
87104
};
88105

89106
void testAttributeRead()
90107
{
91-
const int numThreads = 100;
92-
93-
TestSceneCache task;
94-
std::vector< tbb::tbb_thread *> threads;
95-
96-
for ( int i = 0; i < numThreads; i++ )
97-
{
98-
threads.push_back( new tbb::tbb_thread( task, i ) );
99-
}
100-
for ( int i = 0; i < numThreads; i++ )
101-
{
102-
threads[i]->join();
103-
}
104-
for ( int i = 0; i < numThreads; i++ )
105-
{
106-
delete threads[i];
107-
}
108-
BOOST_CHECK( task.errors() == 0 );
109-
108+
task_scheduler_init scheduler( 100 );
109+
110+
TestSceneCache task( "w" );
111+
112+
parallel_reduce( blocked_range<size_t>( 0, 100 ), task );
113+
BOOST_CHECK( task.errors() == 0 );
114+
}
115+
116+
void testFakeAttributeRead()
117+
{
118+
task_scheduler_init scheduler( 100 );
119+
120+
TestSceneCache task( "fake" );
121+
122+
parallel_reduce( blocked_range<size_t>( 0, 100 ), task );
123+
BOOST_CHECK( task.errors() == 100000 );
110124
}
111125

112126
};
@@ -119,6 +133,7 @@ struct SceneCacheThreadingTestSuite : public boost::unit_test::test_suite
119133
boost::shared_ptr<SceneCacheThreadingTest> instance( new SceneCacheThreadingTest() );
120134

121135
add( BOOST_CLASS_TEST_CASE( &SceneCacheThreadingTest::testAttributeRead, instance ) );
136+
add( BOOST_CLASS_TEST_CASE( &SceneCacheThreadingTest::testFakeAttributeRead, instance ) );
122137
}
123138
};
124139

0 commit comments

Comments
 (0)