Skip to main content
Ben Nadel at the jQuery Conference 2010 (Boston, MA) with: Blain Smith
Ben Nadel at the jQuery Conference 2010 (Boston, MA) with: Blain Smith

GetTempFile() Creates 0KB Files In ColdFusion

By
Published in

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

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel