Troubleshooting

How to Fix CFThread Hanging or Not Completing

Overview of the Problem

cfthread hanging or not completing typically refers to threads launched via the cfthread tag that stall, never finish, or fail to return results to the calling page. Symptoms include requests waiting forever on a join, orphaned work that never ends, or intermittent timeouts and application slowdowns. It happens when threads are blocked on locks, starved due to exhausted thread pools, stuck on I/O (database, HTTP, file), or silently erroring without surfacing exceptions to the parent page.

Why it happens:

  • CFTHREAD runs work asynchronously in a separate thread pool. If you don’t manage timeouts, locks, or exceptions, the thread can wait indefinitely.
  • External dependencies (database, network) may hang.
  • Misconfiguration (thread pool limits, request timeouts) can cause starvation or premature termination.
  • Coding pitfalls (missing join, shared scope access without locks) can deadlock or lose errors.

Symptoms You Might See

  • The parent request waits on cfthread action=”join” and never returns.
  • Threads show “RUNNING” or “WAITING” indefinitely in monitoring tools.
  • Application slows over time; new threads don’t start (pool exhaustion).
  • Logs show request timeouts but no clear error from the thread itself.
  • Intermittent completion: sometimes the same code works, sometimes it stalls.

Quick Cause/Solution Reference

  • Cause: Thread pool exhaustion (too many threads or stuck threads)

    • Solution: Increase CFTHREAD pool cautiously; fix root cause (long I/O or deadlocks); cap threads per request.
  • Cause: Deadlock due to cflock or shared resource contention

    • Solution: Remove nested or circular locks; minimize lock scope and duration; avoid joining inside a lock.
  • Cause: Unbounded external I/O (DB, cfhttp, file)

    • Solution: Set query/HTTP/file timeouts; add circuit breakers; log slow I/O.
  • Cause: Unhandled exceptions inside CFTHREAD

    • Solution: Wrap thread body with cftry/cfcatch, log errors, inspect cfthread..error after join.
  • Cause: Missing or indefinite join

    • Solution: Use cfthread action=”join” timeout=”…” and handle timeout case.
  • Cause: Request timing out or ending while child threads still running

    • Solution: Ensure required threads are joined before request end; configure request timeout appropriately or move long-running work to a queue.
  • Cause: Contention on shared scopes (application/session/server)

    • Solution: Avoid writing shared state from multiple threads or guard with fine-grained locks.
  • Cause: Tomcat connector or JVM thread starvation

    • Solution: Check connector maxThreads, JVM thread dumps; fix global starvation.
See also  How to Fix ColdFusion Scheduled Task Not Running

Step-by-Step Troubleshooting Guide

1) Reproduce and Baseline

  • Identify the exact operation spawning the thread (URL, action, inputs).
  • Note timing: Does it hang immediately, under load, or after running for hours?
  • Add a unique thread name per operation including timestamp or UUID for traceability.

Example:





2) Observe Thread State and Health

  • Use GetThreadList() to inspect thread statuses.

Look for many RUNNING/WAITING threads with old start times, which may indicate deadlock or I/O stalls.

  • Check ColdFusion logs (application.log, exception.log, coldfusion-error.log) for timeouts or errors at the time of the hang.

  • Use Performance Monitoring Toolset (PMT), Server monitor, or FusionReactor to see thread activity and stack traces.


3) Add Defensive Joins with Timeouts

Never wait forever. Join with a timeout and handle the timeout case.














<cfif structKeyExists(reportThread, “error”)>

<cfelseif NOT structKeyExists(reportThread, “result”)>


This pattern prevents the parent from blocking forever and lets you detect exceptions that otherwise wouldn’t bubble up.


4) Set Timeouts on External Calls

Long I/O is a top cause of hanging threads.

  • Database:


/* Your SQL */

  • HTTP:

  • File I/O:
  • Avoid holding locks while doing large reads/writes.
  • For CFFile, be mindful of network drives and OS locks; add retry/backoff logic.

5) Check for Locking and Deadlocks

Misused cflock or shared scope access causes circular waits.

  • Anti-pattern (parent holds lock while waiting on child thread that needs same lock):








This can deadlock.

  • Fix:
    • Don’t join inside locks; reduce lock scope.
    • Use read-only access where possible; aggregate in local variables first, then write shared state briefly under a lock.

6) Verify Thread Pool and Server Tuning

Symptoms of pool exhaustion: New CFTHREAD tags do not start; GetThreadList shows many long-lived threads.

Actions:

  • Temporarily increase CFTHREAD pool (e.g., from 10 to 25) only for testing.
  • Prefer to reduce thread count per request and fix root cause of long-lived threads.
  • Ensure connector (Tomcat) maxThreads is not starved compared to request load.

Tomcat server.xml example snippet:

<Connector port=”8500″ protocol=”HTTP/1.1″
maxThreads=”400″
acceptCount=”200″
connectionTimeout=”20000″ />

Adjust cautiously, monitor CPU and memory.


7) Capture Java Thread Dumps When Hung

If threads are persistently stuck, capture a stack trace to see exactly where they’re blocked:

  • On Linux:

    • jcmd Thread.print
    • or jstack > dump.txt
  • On Windows:

    • Use jstack.exe or JVM tools like Java Mission Control.

Look for:

  • WAITING on coldfusion.runtime.* locks
  • JDBC driver waits (database blocking)
  • java.net.SocketInputStream.* (network I/O)
  • File I/O locks
See also  How to Fix File Upload Failures in ColdFusion

Sample snippet:

“cfthread-Worker-28” #317 prio=5 os_prio=0 tid=0x… WAITING
java.lang.Object.wait(Native Method)
coldfusion.runtime.CFMutex.lock(CFMutex.java:…)
coldfusion.tagext.lang.LockTag.doStartTag(LockTag.java:…)

This indicates a lock wait; review your cflock usage.


8) Ensure Correct Variable Scoping and Data Passing

Inside a cfthread, the Variables/Local scope is separate. Don’t assume access to the parent’s local variables.

  • Properly pass data using attributes:





  • Avoid writing to shared scopes (Application, Server, Session) from multiple threads without careful locking and small critical sections.

9) Handle Errors Explicitly Within Threads

Exceptions inside CFTHREAD do not automatically throw to the caller. Always wrap with try/catch and store/log the exception.














10) Consider Asynchronous Alternatives for Long Jobs

If the work is long-running or not user-critical:

  • Queue jobs (CF Scheduler, Message Queue, async event gateways, or a job runner) instead of doing them inside request/response life cycle.
  • Provide user-facing status via polling rather than tying up request threads.

Common Causes Explained

Thread Pool Exhaustion

Excessive threading per request (e.g., spawning dozens of threads) and long-running child threads can consume the limited CFTHREAD pool. New threads will queue and may appear “hung.”

  • Fix: Cap threads per request (often 2–4 is plenty), ensure each thread has strict timeouts, and shrink the work performed.

Database Locks and Long Queries

Threads may be blocked by DB locks or inefficient queries.

  • Fix: Add cfquery timeout, ensure proper indexing, isolate write operations, and verify DB isolation level. Inspect DB server for lock waits.

Network/DNS/TLS Issues

cfhttp may hang on DNS resolution or TLS handshake.

  • Fix: Set connectiontimeout, consider a local DNS resolver, validate TLS endpoints and cipher compatibility, and use short fail-fast timeouts with retry/backoff.

Locking and Shared State Deadlocks

Nested locks or circular dependencies cause deadlocks.

  • Fix: Avoid long locks; never join inside a lock; lock only the minimal update region.

Unhandled Exceptions Inside Threads

Errors vanish if not captured, leading to threads that silently did nothing.

  • Fix: cftry/cfcatch with logging; inspect thread scope after join.

Common mistakes and How to Avoid Them

  • Mistake: Not setting timeouts on joins and I/O.

    • Avoid: Always use join timeout and timeouts on cfquery/cfhttp.
  • Mistake: Spawning many threads to “speed up” everything.

    • Avoid: Start small (2–4), measure, and only increase if CPU and I/O permit.
  • Mistake: Using shared scopes without protection.

    • Avoid: Use local data; if you must share, lock briefly and consistently.
  • Mistake: Joining inside a CFLock.

    • Avoid: Join outside any locks.
  • Mistake: Reusing thread names inside the same request.

    • Avoid: Generate unique names per thread to prevent collisions.
  • Mistake: Assuming parent variables are visible inside thread.

    • Avoid: Pass needed values via attributes.
  • Mistake: Letting child threads outlive the request unintentionally.

    • Avoid: Join critical threads or offload to background job systems.

Example: Safe Parallelization Pattern











SELECT * FROM big_table WHERE id =

























Diagnostics: What to Look for in Logs

  • application.log: Request timeouts, scheduler interactions.
  • exception.log / coldfusion-error.log: Uncaught exceptions in threads (if logged).
  • Your custom thread log: Add cflog lines in every thread start/end and on catch.
  • PMT/FusionReactor: Track slow transactions, thread states, and stack traces.
See also  How to Resolve ColdFusion Admin API Authentication Failures

Sample custom log lines:




Best practices and Prevention Tips

  • Bound everything:
  • Keep thread count modest:
    • Start with 2–4 threads; measure throughput and CPU before increasing.
  • Fail fast and log:
    • cftry/cfcatch in every thread; log start/end and exceptions with identifiers.
  • Avoid sharing mutable state:
    • Use local variables; if shared writes are necessary, keep locks short and never join within them.
  • Monitor proactively:
    • Use PMT or FusionReactor. Alert on long-running threads and growing thread queues.
  • Separate long jobs from requests:
    • Use queues, Scheduled tasks, or background services for expensive workloads.
  • Review server tuning quarterly:
    • CFTHREAD pool size, request timeout, Tomcat connector threads, JVM GC logs.
  • Test failure modes:
    • Simulate DB slowness, DNS failure, and thread pool exhaustion in staging.

Key Takeaways

  • CFTHREAD hangs usually stem from unbounded waits: missing joins, no I/O timeouts, deadlocks, or pool exhaustion.
  • Always join with a timeout and set timeouts on all external calls.
  • Wrap thread bodies with cftry/cfcatch and log errors; inspect thread scope after join.
  • Keep thread counts small and avoid shared mutable state; lock sparingly.
  • Use monitoring and thread dumps to pinpoint where threads are stuck.
  • For truly long-running work, prefer background job systems over in-request threads.

FAQ

Pourquoi mes threads CFTHREAD ne démarrent-ils pas sous charge élevée ?

This often indicates CFTHREAD pool exhaustion or global thread starvation. Check ColdFusion’s CFTHREAD pool limit and Tomcat connector maxThreads. Reduce the number of threads spawned per request, add timeouts to ensure threads complete, and confirm no deadlocks are holding threads indefinitely.

Comment récupérer les erreurs lancées à l’intérieur d’un CFTHREAD ?

Wrap the thread code in cftry/cfcatch, store the caught exception in thread.error, and join the thread with a timeout. After the join, inspect cfthread..error to handle or log the issue. Errors inside threads do not automatically bubble to the caller.

Que faire si une requête parent se termine avant la fin des threads enfants ?

If the parent request times out or finishes, child threads may be terminated or left running depending on Configuration and version. Ensure critical work is joined before the response ends, or move the work to a background queue (scheduler/message queue) so the user request can return quickly.

Comment éviter les interblocages (deadlocks) liés à CFLock ?

Never join threads while holding a lock, avoid nested or circular locks, keep lock scope and duration minimal, and only lock when mutating shared state. Prefer read-only access without locks and aggregate results locally before a short, single write under lock.

Quels outils recommandez-vous pour diagnostiquer des threads bloqués ?

Use ColdFusion PMT/Server monitor or FusionReactor to view thread states and stack traces. For deep analysis, capture Java thread dumps with jstack/jcmd and check where threads are waiting (DB, network, locks). Review ColdFusion logs and add custom cflog statements in thread code for end-to-end visibility.

About the author

Aaron Longnion

Aaron Longnion

Hey there! I'm Aaron Longnion — an Internet technologist, web software engineer, and ColdFusion expert with more than 24 years of experience. Over the years, I've had the privilege of working with some of the most exciting and fast-growing companies out there, including lynda.com, HomeAway, landsofamerica.com (CoStar Group), and Adobe.com.

I'm a full-stack developer at heart, but what really drives me is designing and building internet architectures that are highly scalable, cost-effective, and fault-tolerant — solutions built to handle rapid growth and stay ahead of the curve.