RC3: Bug in Paste related to deleted DSO
by Tom Spilman · in Torque Game Builder · 06/19/2006 (10:35 pm) · 2 replies
Ok this one is a little complex to understand. The assertion occurs only in debug builds... but it's something that only by chance doesn't cause a crash in release. The assertion:
This happens when i cut and paste in a debug build of TGB. It occurs because tools\levelEditor\data\clipboard.cs.dso is deleted after the ResourceManager enumerates it at startup. Then when when clipboard.cs is exec()'d as part of the paste operation, ResourceManager->find() happily returns a valid ResourceObject for a DSO which does not exist and causes this assertion when reading the DSO version number.
The correct fix seems to be in ResourceManager::openStream... it fails to check if the file was really opened:
The initial fix is simple...
This should have been the only fix necessary as every place in Torque should check the result of OpenStream. Well only one place in Torque is the return value not checked.... in ConsoleFunction(exec) exactly where our original bug was occurring...
The fix again is simple...
And this seems to fix it. I'm a little worried as this seems like such a basic bug to have in such a well tested part of Torque, but TGB does go out of it's way to delete a DSO at runtime... something that isn't commonly done.
Someone should also check if this bug is present in TGE and TSE... i figure this fix should be applied there as well.
Quote:
Fatal: (c:\projects\kvk\engine\source\core\filestream.cc @ 187) FileStream::_read: the stream isn't open
This happens when i cut and paste in a debug build of TGB. It occurs because tools\levelEditor\data\clipboard.cs.dso is deleted after the ResourceManager enumerates it at startup. Then when when clipboard.cs is exec()'d as part of the paste operation, ResourceManager->find() happily returns a valid ResourceObject for a DSO which does not exist and causes this assertion when reading the DSO version number.
The correct fix seems to be in ResourceManager::openStream... it fails to check if the file was really opened:
Stream * ResManager::openStream (ResourceObject * obj)
{
// if filename is not known, exit now
if (!obj)
return NULL;
if (echoFileNames)
Con::printf ("FILE ACCESS: %s/%s", obj->path, obj->name);
// used for openStream stream access
FileStream *diskStream = NULL;
// if disk file
if (obj->flags & (ResourceObject::File))
{
diskStream = new FileStream;
diskStream->open (buildPath (obj->path, obj->name), FileStream::Read); // No check for success!
obj->fileSize = diskStream->getStreamSize ();
return diskStream;
}The initial fix is simple...
// if disk file
if (obj->flags & (ResourceObject::File))
{
diskStream = new FileStream;
if ( !diskStream->open (buildPath (obj->path, obj->name), FileStream::Read) )
{
delete diskStream;
return NULL;
}
obj->fileSize = diskStream->getStreamSize ();
return diskStream;
}This should have been the only fix necessary as every place in Torque should check the result of OpenStream. Well only one place in Torque is the return value not checked.... in ConsoleFunction(exec) exactly where our original bug was occurring...
// If we had a DSO, let's check to see if we should be reading from it.
if(compiled && rCom && (!rScr || Platform::compareFileTimes(comModifyTime, scrModifyTime) >= 0))
{
compiledStream = ResourceManager->openStream(nameBuffer);
// Check the version!
compiledStream->read(&version);
if(version != Con::DSOVersion)
{
Con::warnf("exec: Found an old DSO (%s, ver %d < %d), ignoring.", nameBuffer, version, Con::DSOVersion);
ResourceManager->closeStream(compiledStream);
compiledStream = NULL;
}
}The fix again is simple...
// If we had a DSO, let's check to see if we should be reading from it.
if(compiled && rCom && (!rScr || Platform::compareFileTimes(comModifyTime, scrModifyTime) >= 0))
{
compiledStream = ResourceManager->openStream(nameBuffer);
if ( compiledStream )
{
// Check the version!
compiledStream->read(&version);
if(version != Con::DSOVersion)
{
Con::warnf("exec: Found an old DSO (%s, ver %d < %d), ignoring.", nameBuffer, version, Con::DSOVersion);
ResourceManager->closeStream(compiledStream);
compiledStream = NULL;
}
}
}And this seems to fix it. I'm a little worried as this seems like such a basic bug to have in such a well tested part of Torque, but TGB does go out of it's way to delete a DSO at runtime... something that isn't commonly done.
Someone should also check if this bug is present in TGE and TSE... i figure this fix should be applied there as well.
About the author
Tom is a programmer and co-owner of Sickhead Games, LLC.
Associate Justin DuJardin
Default Studio Name
This has been fixed and will be in the 1.1.1 release. I agree it is odd that such a bug could exist, but as you said, we have made it a habbit of going out of our way to make the system 'flex' as much as we can. I like to think Torque is just working the kinks out of some its muscles it's never really used before :)
Cheers,
-Justin