ColdFusion : terminate CFTHREAD in separate request - coldfusion

I am using CFTHREAD in my ColdFusion application. From what I've read from Ben Nadel (https://www.bennadel.com/blog/2980-terminating-asynchronous-cfthreads-in-coldfusion.htm) ColdFusion only exposes and tracks threads in the current request. In my situation, I am spawning a thread via an ajax call and then providing the user with a cancel button. I was hoping the cancel button could call the terminate method on the thread, but no matter where I store it (application,server,session) ColdFusion always returns an error that it was unable to terminate thread "THREAD_NAME" because "THREAD_NAME" was not spawned.
I know that under the hood, ColdFusion is mostly Java. So I'm hoping that there may be a way. Could anyone either confirm or deny this possibility? Any example of how?
Thanks!

Sorry, I don't have a 50 reputation to comment, so I'll post this as an answer. Recently, I was in the same situation with a CFThread spawned via ajax and I needed to terminate it somehow but was unable to. I had a CFQuery inside a CFLoop that used its datasource in the application scope. So what I came up with was to sign into ColdFusion Administrator and temporarily renaming the datasource which caused the thread to throw a database error. While it was inelegant termination, it served the purpose at the time.
So after seeing this question it got me thinking about a possible workaround if there isn't a known way to accomplish this. Suppose during your thread processing, it tests for the value of a variable in the application/server/session scope. Supposing the value is initially set to "true" and then subsequently set to "false" by another process, when the thread finds the false value, it can terminate gracefully.

Can you?
Yes, but only using internal classes. When the cfthread is created, use the local THREAD_NAME to retrieve a reference to the underlying thread object.
context = getPageContext().getFusionContext();
thread = context.getUserThreadTask( "theLocalTaskName" );
Since the local name can be used by multiple requests, the reference should be stored under a unique name, like a uuid. The reference is actually an instance of an internal class coldfusion.threads.Task. To terminate it, call its cancel() method.
thread.cancel();
Should you?
That's a big question and all depends on what the thread does - how it does it - and how the resources it uses would be affected if the process just stops dead, midstream, with no warning.
The reason is that calling <cfthread action="terminate"..> kills the thread - instantly. CF doesn't care if it's in the middle of a critical section. The server just whacks it with a mallet and stops it cold. The exception logs show that CF does this by invoking Thread.stop()
"Information","cfthread-47","09/07/19","17:10:44","","THREAD_V_2: Terminated"
java.lang.ThreadDeath
at java.base/java.lang.Thread.stop(Thread.java:942)
at coldfusion.thread.Task.cancel(Task.java:257)
at coldfusion.tagext.lang.ThreadTag.terminateThread(ThreadTag.java:345)
at coldfusion.tagext.lang.ThreadTag.doStartTag(ThreadTag.java:204)
The java documentation says stop() method is deprecated because it's inherently unsafe:
Stopping a thread causes it to unlock all the monitors that it has
locked. (The monitors are unlocked as the ThreadDeath exception
propagates up the stack.) If any of the objects previously protected
by these monitors were in an inconsistent state, other threads may now
view these objects in an inconsistent state. Such objects are said to
be damaged. When threads operate on damaged objects, arbitrary
behavior can result. This behavior may be subtle and difficult to
detect, or it may be pronounced. Unlike other unchecked exceptions,
ThreadDeath kills threads silently; thus, the user has no warning that
his program may be corrupted. The corruption can manifest itself at
any time after the actual damage occurs, even hours or days in the
future.
So it's important to consider what a thread actually does, and determine if it's even safe to terminate. For example, if a thread processes a file with FileOpen(), forcibly terminating it might prevent the thread from releasing the handle, leaving the underlying file in a locked state, which is undesirable.
The recommended way of stopping threads in java is with an interrupt(). That's essentially the concept user12031119 described. An interrupt doesn't forcibly kill a thread. It's just a flag that suggests a thread stop processing. Leaving it up to the thread itself to determine when it's safe to exit. That allows threads to finish critical sections or perform any cleanup tasks before terminating. Yes, it requires a little more coding, but the results are much more stable and predictable than with "terminate".

What you will want to do is setup a data structure somewhere like application or session scope that keeps track of threads running that you want to be able to cancel.
Application.cfc OnApplicationStart
<cfset application.cancelThread = {} />
Before entering thread create id and then pass into thread
<cfset threadId = createUUID() />
<cfset application.cancelThread[threadId] = false />
Pass the threadId back to the client for the cancel button. On click of the cancel button pass back the threadId
<cfset application.cancelThread[form.threadId] = true />
During thread execution
<cfif application.cancelThread[threadId]>
<cfabort />
<!--- or your chosen approach to ending the processing --->
</cfif>
If thread reached end then remove thread reference
<cfset structDelete(application.cancelThread, threadId) />

Related

Converting a Console Program into an MFC app (Thread issues) (Pleora SDK)

Back to stackoverflow with another question after hours of trying on my own haha.
Thank you all for reading this and helping in advance.
Please note the console program has following functionalities:
connect to a frame grabber
apply some configs
store the incoming data (640 * 480 16-bit grayscale imgs) in a stream of buffers inside a while loop
Exits the while loop upon a key press.
disconnect from device
And I'm only adding the displaying the images functionality on the MFC GUI app. In short,
i) Converting a console app to an MFC app (dialog based)
ii) decided to use thread for displaying images, but DK how to properly exit from thread when there are certain tasks to be done (such as call disconnectFromDevice(); freeBuffers();, etc) before exiting the thread.
iii) have tried making the while loop condition false but didn't work
( I actually want this to be a callback function that's called repeatedly but IDK how to implement it inside a thread)
iv) forcing AfxEndThread didn't work and it's not even the way it should be done (I think).
So my question is,
1. Are you supposed to use a while loop to excuete a certain job that should repeatedly be done? If not, do you have to implement a callback inside a thread? Or use Windows message loop? Why and how? Please provide a hello-world-like sample code example
(for example, you are printing "hello world" repeatedly inside a thread with a condtion in an MFC GUI app. How do you update or check the condition to end the thread if you can't just AfxEndThread() inside the threadproc)
2. If it's ok with a while, how do you exit from the while loop, in other words how do you properly update the exit condition outside the thread the while loop's in?
Please refer to the source code in the provided link
ctrl+F OnBnClickedConnectButton, AcquireImages and OnBnClickedDisconnectButton
https://github.com/MetaCortex728/img_processing/blob/main/IR140Dlg.cpp
Worker threads do not have message-queues, the (typically one and only) UI one does. The message-queue for a thread is created by the first call of the GetMessage() function. Why use messages to control processing in a worker thread? You would have to establish a special protocol for this, defining custom messages and posting them to the queue.
Worker threads can be implemented as a loop. The loop can be terminated based on various conditions, like failures to retrieve any data or request from the user. You can simply exit the thread proc to terminate the thread's execution. If the thread doesn't respond it may have stuck (unless it performs a really lengthy operation) and the UI thread must provide some mechanism to kill it. That is first request termination and if it doesn't respond within some set time then kill it.
The condition mechanism to terminate should best be some synchronization object (I would recommend a manual-reset event), interlocked variable or a simple boolean which you should access and set using a critical section.
Some considerations:
You pass a parameter block to the thread. Make sure that it remains alive throughout the thread's lifetime. For example, it should NOT be a local variable in a function that exits before the thread's termination.
The loop must be "efficient", ie do not loop infinitely if data are not available. Consider using blocking functions with timeouts, if available.
Resource management (eg connecting/disconnecting, allocating/releasing etc) should best be performed by the same thread.
An alternative implementation can be APCs. Then the thread's proc function is a while(!bTerminate) { SleepEx(INFINITE, TRUE); } loop, and other threads issue requests using a the QueueUserAPC() function.
The AfxEndThread(0) call in OnBnClickedDisconnectButton() is wrong, it terminates the current thread, which in this case is the main (UI) thread. Check the documentation.
A sidenote, my suggestion about the project type is not a dialog-based application but instead a normal MFC application without a document class (uncheck the Document/View architecture support option), as it offers features like menus, toolbars and the like, and most importantly the ON_UPDATE_COMMAND_UI handlers.

Is cfexecute timeout=0 as good as cfthread action=run if no output needed?

Looking at some legacy code and the programmer in question uses:
<cfthread action="run">
<cfexecute name="c:\myapp.exe" timeout="30">
</cfthread>
Can one safely replace the code above with this?
<cfexecute name="c:\myapp.exe" timeout="0">
Is CF going to spawn up a thread in the code above anyway? And is the thread going to be counted towards "Maximum number of threads available for CFTHREAD"?
If the intent is to have a non-blocking flow of the code, then you can safely replace the earlier code with yours.
In my understanding, CF is not creating a thread when it gets a timeout="0". It must be just calling the exe (which creates a new process on server) and never wait for the process to reply. So, nothing is added to the thread limit count.

ColdFusion performance and locking optimisation

I have a link that will allow users to click it and it fetches a zip file of photos. If the zip file doesn't exist, it then starts a thread to create the zip and displays a message back to the user that the photos are currently being processed.
What I'm trying to avoid is a user clicking the link repeatedly and setting off a whole mass of threads that will try create/update the zip file. The zip file processing is quite system resource intensive so I only want to allow the application to generate one zip at a time. If one is busy being compiled, it should just do nothing and queue the requests.
Currently how I am handling it is with a cflock around the thread:
<cflock name="createAlbumZip" type="exclusive" timeout="30" throwontimeout="no">
<cfthread action="run" albumId="#arguments.albumId#" name="#CreateUUID()#">
....
What I am hoping occurs here (it seems to be working if I test it) is that it will check if there is currently a thread running using a lock called 'createAlbumZip'. If there is, it will queue the request for 30 seconds after which it should timeout without any error. If it wasn't able to create it within the 30 seconds that is fine.
So - this seems to be working, but my question is: Is this the best way to handle a scenario like this? Is locking the right approach? Are there any shortcomings that could arise from this approach that I don't see?
There are a million ways to skin this cat. Locking is a good start, and as per your comment on #Pat Branley's answer, I think your locking outside the thread creation might be a little more efficient for just the reason you propose: the potential would exist to create dozens of threads whose whole lifespan will consist of waiting for a lock to open or timeout.
The other thing you need to do is double up on the IF statement:
<cfif not (zip file exists)>
<cflock ...>
<cfif not (zip file exists)>
<cfthread>
...create zip...
</cfthread>
</cfif>
</cflock>
</cfif>
This will prevent the case where thread B is waiting while thread A creates the zip, and then thread A finishes, and thread B proceeds to recreate/overwrite it.
In addition, you could consider something like using JavaScript to prevent extra clicks by disabling the button/link after it's been clicked.
I think you have that code around the wrong way. What you are saying is 'only one thread is allowed to spawn this new thread'. Now that may work in your case because you have the timeouts set such that nobody can create another thread so there is no chance two threads are executing at once.
what you want to say is 'only one thread is allowed to make a zip'. So I would do this
<cfthread .... >
<cflock>
...zip....

Number of parallel instances of my process (app)

Is there some portable way to check the number of parallel instances of my app?
I have a c++ app (win32) where I need to know how often it was started. The problem is
that several user can start it parallel (terminal server), so i cannot search the "running process" list because I'm not able to access the the list of other users.
I tried it with Semaphore (boost & win32 CreateSemaphore)
It worked, but now I have the problem if the app crashes (Assertion or just kill the process) the counter is not changed. (rebooting helps)
Also manually removing/resetting the semaphore counter in my code is not possible because I don't know if somebody else is running my application.
Edited to add:
Suppose you have a license that lets you run 20 full-functionality copies of your program. Then you could have 20 mutexes, named MyProgMutex1 through MyProgMutex20. At startup, your program can loop through the mutexes. If it finds a spare mutex that it can take, it stops looping and enters full-functionality mode. If it loops through all the mutexes without being able to take any of them, then it enters reduced-functionality mode.
Original answer:
I assume you want to make sure that only one copy of your process runs at once. (Or, for Terminal Server, one copy of your process per login session).
Your named semaphore solution is close. The right way to do this is a named mutex. Use CreateMutex to make the mutex, then call WaitForSingleObject with a timeout of zero. If WaitForSingleObject returns WAIT_TIMEOUT, another copy of the process is running. If it returns WAIT_OBJECT_0 or WAIT_ABANDONED, then you are the only copy of the process. You need to keep the mutex handle open while your program runs - either call CloseHandle when your process is about to exit, or just deliberately leak the handle and rely on Window's built-in cleanup to release the handle for you when your process exits. Windows will automatically increment the mutex's counter when your process exits.
The only thing I can think of that mitigates the problem of crashed processes is a kind of “dead man’s switch”: each process needs to update its status in regular intervals. If a process fails to do this, it’s automatically discarded from the list of active processes.
This technique requires that one of the processes acts as a server which keeps tab of whether other processes have updated recently. If the server dies, then another process can take over. This, in turn, requires that each process tests whether there still is a server alive.
Alternatively, each process can be its own server and keep track locally. This may be easier to implement than server-switching.
You can broadcast message and other instances of your application should send some response. You count responses - you get number of instances.

Application Object and Concurrency Concerns

In some asp tutorials, like this, i observe the following pattern:
Application.Lock
'do some things with the application object
Application.Unlock
However, since web pages can have multiple instances, there is an obvious concurrency problem. So my questions are the following:
What if one page tries to lock while the object is already locked?
Is there a way to detect whether the application object is locked?
Is it better to just work on an unlocked application object or does that have other consequences?
What if there is only one action involving the application object? ~Is there a reason to lock/unlock in that case?
From the MSDN documentation:
The Lock method blocks other clients from modifying the variables stored in the Application object, ensuring that only one client at a time can alter or access the Application variables.
If you do not call the Application.Unlock method explicitly, the server unlocks the locked Application object when the .asp file ends or times out.
A lock on the Application object persists for a very short time because the application object is unlocked when the page completes processing or times out.
If one page locks the application object and a second page tries to do the same while the first page still has it locked, the second page will wait for the first to finish, or until the Server.ScriptTimeout limit is reached.
An example:
<%# Language="VBScript" %>
<%
Application.Lock
Application("PageCalls") = Application("PageCalls") + 1
Application("LastCall") = Now()
Application.Unlock
%>
This page has been called <%= Application("PageCalls") %> times.
In the example above, the Lock method prevents more than one client at a time from accessing the variable PageCalls. If the application had not been locked, two clients could simultaneously try to increment the variable PageCalls.
There will be consequences if you use the application object unlocked. For example if you want to implement a global counter:-
Application("myCounter") = Application("myCounter") + 1
The above code will at times miscount. This code reads, adds and assigns. If two threads try to perform this at the same time they may read the same value and then subsequently write the same value incrementing myCounter by 1 instead of 2.
Whats needed is to ensure that the second thread can't read myCounter until the second thread has written to it. Hence this is better:-
Application.Lock
Application("myCounter") = Application("myCounter") + 1
Application.Unlock
Of course there are concurrency issues if the lock is held for a long time especially if there are other uses for application which are unaffected by the code holding the lock.
Hence you should avoid a design that would require a long lock on the application.
If one page tries to lock the Application object while it is already locked, it will wait until the page holding the lock has released it. This will normally be quick (ASP code should only generally hold the lock for long enough to access the shared object that's stored in Application).