Skip to main content
Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.

RequestTimeout Setting Affects CFThread Execution In Lucee CFML 5.3.6.61

By Ben Nadel on
Tags: ColdFusion

Yesterday, when I was exploring task threads in Lucee CFML, I noticed that my long-running CFThread tags were suddenly dying at around 30-seconds of execution time. And, after I poked around in the Lucee Administrator, I noticed that the default request timeout for the server was set to 30-seconds. I didn't realize this, but apparently the CFSetting tag's requestTimeout property affects both top-level page requests as well as daemon CFThread tags. To confirm this, I wanted to set up a simple test in Lucee CFML 5.3.6.61.

To test this, I set up a page that programmatically sets a short requestTimeout and then spawns a CFThread tag that uses a sleep() command to make sure that its execution time takes longer that the define timeout:

<cfscript>

	// Setting a request-timeout of 3-seconds.
	setting
		requestTimeout = createTimeSpan( 0, 0, 0, 3 )
	;

	thread
		type = "daemon"
		name = "testThread"
		{

		// Attempting to override the request-timeout for this CFThread.
		// --
		// CAUTION: THIS DOES NOT WORK.
		setting
			requestTimeout = createTimeSpan( 0, 0, 0, 30 )
		;

		systemOutput( "CFThread started, about to sleep().", true, false );
		sleep( 5000 );
		systemOutput( "CFThread completed successfully.", true, false );

	}

	// Store a reference to the thread we just created so that we can view the status
	// of it in another script.
	application.testThread = cfthread.testThread;

	echo( "CFThread initiated." );

</cfscript>

As you can see, I'm setting the CFSetting timeout to be 3-seconds. Then, within the CFThread tag, I'm sleeping for 5-seconds (which is longer than the 3-second timeout). For debugging, I'm storing the thread reference in the application scope so that I can dump() it out on another page:

<cfscript>

	if ( application.keyExists( "testThread" ) ) {

		// Dump CFThread data (without the Error, which is output next).
		dump(
			label = "Test Thread",
			var = application.testThread,
			hide = "Error"
		);

		// If CFThread ended in error, output the error.
		// --
		// NOTE: I'm hiding some keys just to make the output easier to read.
		if ( application.testThread.keyExists( "Error" ) ) {

			dump(
				label = "Test Thread Error",
			 	var = application.testThread.Error,
			 	hide = "StackTrace,TagContext"
			 );

		}

	}

</cfscript>

Now, if we run the page that spawns the CFThread tag and then check the debugging page a few seconds later, we see this following ColdFusion error:

A CFThread tag that was terminated due to CFSetting RequestTimeout in Lucee CFML.

As you can see, the CFThread tag ended with status TERMINATED. And, the ColdFusion error appended to the CFThread tag indicates a "request timeout". As such, we can conclude that the CFThread tag execution life-span was directly influenced by the requestTimeout setting on the CFSetting tag. We can also see that my attempt to override the CFSetting tag inside the CFThread tag did not impact the overall execution of the script.

So, it turns out this was a pretty large blind-spot in my understanding of how the CFThread tag executes in a ColdFusion application. I always just assumed that the CFThread tags would execute indefinitely in the background (assuming no bugs, of course). But, it turns out that the request timeout settings affect both the top-level and the child threads within the Lucee CFML application.



Reader Comments

@Elliott,

Hey man -- long time no talk :D Good to hear from you! I'm actually trying to use this approach right now in my previous exploration on using Task threads. Initial findings are a bit confusing - originally, my threads were seemingly "completed" at about 30-seconds. But now, if I set the request-timeout to 1-min in the Task thread, my daemon threads all seem to be "completing" in 6-12-seconds.... which is the wrong direction 🤔

I'll keep tinkering.

Reply to this Comment

Ahhhh, d'uh. My initial attempt to use the CFSetting tag was trying to use the createTimeSpan() function for the requestTimeout. It's been a long time since I've even used this tag. But, it doesn't work that way :D You have to provide a number of seconds, not a time span. When I switch over to something like:

setting
	requestTimeout = ( 60 * 5 )
;

... in the Task thread, then the Daemon threads live much longer.

Reply to this Comment

@All,

This morning, I wanted a quick sanity-check to make sure that a long-running CFThread tag - that exceeds the duration of the parent page-request - can still call "back into" the timed-out page request:

www.bennadel.com/blog/3903-calling-into-a-timed-out-parent-page-context-from-a-cfthread-tag-in-lucee-cfml-5-3-6-61.htm

"Page Context" is a funky concept in ColdFusion, so I am sure I am missing some edge-cases here; but, at least for my typical use-case, which is invoking methods on the variables scope (normally as part of a ColdFusion Component context), this seem to "just work". Noice!

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Blog
Live in the Now
Oops!
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.