Skip to main content
Participating Frequently
August 12, 2011
Question

Threads spawned by <CFTHREAD> are queued but never run

  • August 12, 2011
  • 1 reply
  • 2237 views

I was having a problem with some threads spawned by <CFTHREAD> so I wrote a little test program to see if I could figure out what was going on.

<cflock scope="session" type="exclusive" timeout="10">

<cfset session.count = "0">

</cflock>

<cfloop from="1" to="10" index="idx">

   <cfthread name="t#idx#">

      <cflock scope="session" type="exclusive" timeout="10">

      <cfset session.count ++>

      </cflock>

   </cfthread>

</cfloop>

<cfset Sleep(5000)>

<cfdump var="#session#">

Spawns 10 threads each of which increments a session variable, waits a few seconds and checks the results.  As I expected the count variable was still "0".  I tried joining the threads and it just hung until the timeout expired and the variable still wasn't incremented.

I assumed that meant there were some hung threads so I ran the Server Monitor.  Oddly enough it showed 0 active threads and 158 queued threads.  I reran the script above and it then showed 168 queued threads and still no active ones.  If there were hung threads shouldn't they show up as active so I could terminate them?

I had CF restarted, then ran the script above and it produced the expected results (sesson.count = 10).  Checked Server Monitor, 0 active & 0 queued.  Everything back to normal.

Did some more testing with my actual code and the same thing happened again.  So what is going on here?  I had CF restarted again but I'd like to figure out how this can be avoided.  If there actually are hung processes that aren't showing as active in Monitor is there any way I can kill them without having to restart CF?

Any insights are appreciated.

Ken

This topic has been closed for replies.

1 reply

Inspiring
August 12, 2011

Dunno why you're seeing the queuing, but I also dunno why you're locking simple writes to the session scope: this is not CF5 (which was the last version of CF one needed to lock the session scope as a matter of course).  Remove the CFLOCKs and see what you get?

Don't get me wrong, the locking shouldn't cause problems in your example, but equally it's just not necessary these days, so you might as well factor it out as a contributor.

Let's back up a bit.  What was the original problem you were trying to diagnose?

--

Adam

Participating Frequently
August 13, 2011

Thanks for the reply.  I've always used <CFLOCK> when writing to the session scope, having started with CF4.  But I'm certain that's not an issue here.  Anyway I can't test whether that would make any difference as right now everything is fine and I don't really want to duplicate the issue (this test script would not cause a problem in itself, it just illustrates how once whatever is happening happens, any new threads get queued but don't run).

The initial issue was caused by some threads that call a cfc.  Relevant code is below:

<cfif lstIMB is not "">
     <cfobject component="cfc.IMB" name="cfcIMB">
     <cfset cfcIMB.initialize(intTotal)>
</cfif>
<cfset idx = "0">
<cfloop list="#lstIMB#" index="imb">
     <cfthread name="Thread#++idx#" strIMB="#imb#">
          <cftry>
               <cfset sctIMB = cfcIMB.parse(attributes.strIMB)>
               <cfset cfcIMB.add(sctIMB)>
          <cfcatch>
               <cfabort>

          </cfcatch>
          </cftry>
     </cfthread>

</cfloop>

(lstIMB is a list of strings, each of which is parsed and a series of queries is executed, the results of which get put into session variables.)

However I have tried running this code without the <cfthread> and I have also had problems with that.  So I think the underlying problem is with the cfc.  Sometimes it will process the entire list with no problem.  But when there is an error in the first item in the list (which is trapped in the cfc - all the queries have timeout limits, 5 seconds each), the process hangs.  The results of the first loop iteration show up in the session but the second one never returns.

I was intrigued by your comment about cflock being unnecessary - I've heard conflicting info, the docs for CF9 (below) seem to indicate otherwise - this would seem to be the very type of application where it would be called for.

ColdFusion is a multi-threaded server; it can process multiple page requests at a time. Use the cflock tag for these purposes:

  • To ensure that modifications to shared data and objects made in concurrently executing requests occur sequentially.

Inspiring
August 13, 2011

OK, well it does sound like the CFTHREAD avenue was a red herring (to mix metaphors).  Perhaps post the relevent CFC code.

Re the docs: this is just a case of the docs not having been updated for (at least ~) ten years.  That's the exact same text as in the CF5 docs!  And it has not been correct since CF5.

The thing is that when CF was rearchitected in Java, they wrote the session scope (and application scope, and server scope) so reads and writes to it are synchronised, so the CFLOCK equivalent is already being done for you.  When dealing with single statements, it serves absolutely no purpose, other than putting unnecessary load on the server, keeping track of all the locks.

However the risk of race conditions can still occur, which do need to be protected against.  If you have more than one statement in a block of code that needs to be run atomically, then one still needs to lock it.  EG:

<cfparam name="session.foo" value="0">

<cfset sesssion.foo++>

foo is: <cfoutput>#session.foo#</cfoutput>

Two requests concurrent requests might come along and the second request might hit the second line of code before the first request runs the third line of code, meaning the first request will report "2" when one would be expecting it to say "1".  To protect against that, one needs to put a lock around that code.  Make sense?

--

Adam