diff --git a/Changes b/Changes index 6a3527fc18..53a6cda2bc 100644 --- a/Changes +++ b/Changes @@ -1,8 +1,10 @@ 10.5.x.x (relative to 10.5.9.2) ======== +Fixes +----- - +- USDScene : Fixed crash attempting to write to a file that is already open for reading. An exception is now thrown instead. 10.5.9.2 (relative to 10.5.9.1) ======== diff --git a/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp b/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp index dbd1b624a3..ce802c5938 100644 --- a/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp +++ b/contrib/IECoreUSD/src/IECoreUSD/USDScene.cpp @@ -761,11 +761,11 @@ class USDScene::IO : public RefCounted static pxr::UsdStageRefPtr makeStage( const std::string &fileName, IndexedIO::OpenMode openMode ) { + pxr::UsdStageRefPtr stage; switch( openMode ) { case IndexedIO::Read : { static const std::string g_stageCachePrefix( "stageCache:" ); - pxr::UsdStageRefPtr stage; if( boost::starts_with( fileName, g_stageCachePrefix ) ) { // Get Id from filename of form "stageCache:{id}.usd" @@ -779,17 +779,20 @@ class USDScene::IO : public RefCounted { stage = pxr::UsdStage::Open( fileName ); } - if( !stage ) - { - throw IECore::Exception( boost::str( boost::format( "USDScene : Failed to open USD stage : '%1%'" ) % fileName ) ); - } - return stage; + break; } case IndexedIO::Write : - return pxr::UsdStage::CreateNew( fileName ); + stage = pxr::UsdStage::CreateNew( fileName ); + break; default: throw Exception( "Unsupported OpenMode" ); } + + if( !stage ) + { + throw IECore::Exception( boost::str( boost::format( "USDScene : Failed to open USD stage : '%1%'" ) % fileName ) ); + } + return stage; } std::string m_fileName; diff --git a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py index 11fe8a4abf..c73167f2ce 100644 --- a/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py +++ b/contrib/IECoreUSD/test/IECoreUSD/USDSceneTest.py @@ -4313,5 +4313,17 @@ def testSetNameValidation( self ) : with self.subTest( setName = setName ) : self.assertEqual( root.readSet( setName ), IECore.PathMatcher( [ f"/set{setIndex}Member" ] ) ) + def testWriteToOpenScene( self ) : + + # Using posix-format filename, because Windows backslashes don't play nicely + # with `assertRaisesRegex()`. + fileName = ( pathlib.Path( self.temporaryDirectory() ) / "test.usda" ).as_posix() + IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Write ) + + reader = IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Read ) + + with self.assertRaisesRegex( RuntimeError, f"USDScene : Failed to open USD stage : '{fileName}'" ) : + IECoreScene.SceneInterface.create( fileName, IECore.IndexedIO.OpenMode.Write ) + if __name__ == "__main__": unittest.main()