CFThread Must Die (Kill Bill) - Part 1
I saw an interesting question on stackoverflow.com last week asking how to monitor cfthreads when using the CF Standard edition. The Enterprise edition comes with a very slick Server Monitor. However, that is off limits if you are running the Standard Edition. As I am the ever curious type, I decided to do some investigating. After a lot of digging I eventually came up with some (highly experimental) code that seems to work. As the experiment revealed a few interesting things about the internals of cfthreads, I decided to post it for the curious masses.
<cfscript>
CurrentThread = createObject("java", "java.lang.Thread").currentThread();
</cfscript>
Now threads can belong to ThreadGroups. ThreadGroups are a bit like directories. They have a hierarchical structure and groups can contain both Threads and other ThreadGroups (ie files and subdirectories). So in theory you could work your way up the chain to identify all active threads.
A handy snippet from the slightly dated javaalmanac.com site provided an example of how to traverse ThreadGroups and display all active threads. With a small modification I was able to output the names of all my active threads. (The image below is a much condensed version)
That is when I noticed something curious. All of the threads I created started with the name "cfthread". (You have to love development teams that adhere to naming conventions!). The thread status, or more accurately the Thread.State, is similar to cfthread statuses. But with slightly different names: NEW, RUNNABLE, etcetera.
So I decided to try a brute force approach and stop() any cfthreads in a RUNNABLE state. Now, it is worth noting that Thread.stop() was deprecated because it can be unsafe under certain situations. But as this was just an experiment, I decided to give it a whirl.
In the Event of a Zombie Attack...
It seemed to work. But in one or two of my tests, the threads seemed to die. Yet did not seem to be removed from CF's list of running threads. Since the Standard Edition is limited to ten (10) threads, when I tried to fire up new threads they never executed. They just kept piling up in the queue. I am not sure if it was an anomaly or a flaw in my testing. But that, combined with the warnings about Thread.stop() convinced me to try a different approach.
Dumpster Diving
After much digging and copious usage of cfdump, I found a promising method in the FusionContext class called getUserThreadTask(). Following the trail of this method, I discovered that cfthread runs as a type of scheduled task, under a worker thread. Considering the set-it-and-forget-it nature of threads, the fact that they are scheduled was not that surprising.

The Task class looked extremely promising. It seemed to contain all of the methods I would need for tracking and stopping threads. But it took a bit of work to figure how and when to use the getUserThreadTask() method. As I will explain in Part 2.

----------------
* On a totally unrelated note, in case you were wondering, no I did not see the zombie movie referred to in this entry .. thank goodness.
It is late. Time to pack it in before I turn into a pumpkin. Happy Halloween ;) ...Read More