GetTempFile() Creates 0KB Files In ColdFusion
The other day, I happened to notice that a few of our servers had thousands of 0KB files in the temp-directory. After I was able to track down the code that was creating the temp files, I quickly realized what the problem was - the developer thought that the getTempFile() function simply returned a temporary file path; he was not aware (or was not thinking about the fact) that getTempFile() actually creates a file, albeit 0-bytes in size, when called.
The code that I found looked something like this:
<cfscript>
/**
* I do some processing with some temporary files.
*
* @output false
*/
public void function processRequest( required numeric input ) {
// Get a scratch file in the temp directory that we can use to process the input.
var tempFilePath = getTempFile( getTempDirectory(), "processing-#input#-" );
lock
name = "processingRequest"
type = "exclusive"
timeout = 1
{
try {
// Do some processing that may cause the parent LOCK to timeout on
// subsequent requests.
sleep( 5 * 1000 );
// No matter what happens, clean up the scratch file.
} finally {
fileDelete( tempFilePath );
}
} // END: Lock.
}
// ------------------------------------------------------ //
// ------------------------------------------------------ //
processRequest( 4 );
</cfscript>
As you can see, the code makes a good effort to clean-up after itself, deleting the scratch file in the Finally clause of the Try/Catch block. And, if you thought that getTempFile() only returned a file path, this would likely be sufficient. But, since getTempFile() actually creates a file and returns the resultant path, this code has the potential to leave scratch files laying around.
Once you concentrate on the fact that getTempFile() creates a file, it becomes clear that if the control flow can't obtain the Lock, due to the timeout, then the Try/Catch block is never entered. And, if the Try/Catch block is never entered, the Finally block is never executed which means that the temp file is never cleaned-up.
This is what was happening in our code. Luckily, the fix is quite easy - all we have to do is move the getTempFile() request into the Try/Catch block. Doing so will ensure that the temp file only ever gets created in a context that can be cleaned-up:
<cfscript>
/**
* I do some processing with some temporary files.
*
* @output false
*/
public void function processRequest( required numeric input ) {
lock
name = "processingRequest"
type = "exclusive"
timeout = 1
{
try {
// Get a scratch file in the temp directory.
var tempFilePath = getTempFile( getTempDirectory(), "processing-#input#-" );
// Do some processing that may cause the parent LOCK to timeout on
// subsequent requests.
sleep( 5 * 1000 );
// No matter what happens, clean up the scratch file.
} finally {
fileDelete( tempFilePath );
}
} // END: Lock.
}
// ------------------------------------------------------ //
// ------------------------------------------------------ //
processRequest( 4 );
</cfscript>
It's a minor change, but it makes all the difference. Ultimately, though, you just have to realize that the getTempFile() function both creates a file and returns a file path.
Want to use code from this post? Check out the license.
Reader Comments