RequestTimeout Setting Affects CFThread Execution In Lucee CFML 5.3.6.61
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:

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
Looks like this is a pretty old issue, Google finds this first mentioned in 2015:
https://dev.lucee.org/t/disabling-requesttimeout-when-using-cfthread/1989
Looks like the workaround is to use a super long timeout, like years. I'm surprised there isn't a way to detach a thread from the request.
@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.
Ahhhh, d'uh. My initial attempt to use the
CFSetting
tag was trying to use thecreateTimeSpan()
function for therequestTimeout
. 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:... in the Task thread, then the Daemon threads live much longer.
@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!@All,
I recently start to consider "nested threads" or "tail recursion threads" in Lucee CFML. Which got me to revisit this
CFSetting
issue. And, I realized that you can sort of get around the request timeout by breaking your asynchronous processing into smaller threads:www.bennadel.com/blog/3939-recursive-nested-cfthreads-can-get-around-cfsetting-requesttimeout-in-lucee-cfml-5-3-7-47.htm
Meaning, you can exceed the request timeout value as long as no individual
CFThread
exceeds the timeout. But, in aggregate, multipleCFThread
tags can run for a long time.Post A Comment