I have found this nice component called TBackgroundWorker. However, people are criticizing it (on SO) because it uses TerminateThread. Here is the "faulty" code:
destructor TBackgroundWorker.Destroy;
begin
if IsWorking then
begin
TerminateThread(fThread.Handle, 0);
Cleanup(True);
raise EBackgroundWorker.CreateFmt(SInvalidExit, [Name]);
end;
inherited Destroy;
end;
For me it seems a valid destructor. Is it? Should I worry?
There is a better solution?
In my opinion, the destructor is valid.
Forcibly terminating a thread is wrong. Also, raising an exception in a destructor may kill the whole application. However, please don't ignore the context.
We talk about a proxy object that wraps a thread. If such a component is running, its destruction is comparable to killing a running thread. The proxy should fail fast and report such a misaction, not manipulate it. Besides, this is a third-party component, which does not know the intent of the application's developer.
I suppose you disagree with me; otherwise, we didn't have this conversation. Let's see what the alternatives are.
Canceling the task and terminating the thread gracefully, no exception message. With this approach, we are guessing the intention of the developer. If the developer has made a mistake, he or she may never know until it is too late. The application would have unexpected behaviors, and it is very complicated to figure out the source of the issue.
Ignoring the running thread and destroying the component anyway, without raising an exception. Seems like turning a deterministic machine into a non-deterministic one. Do we even need to discuss this?
Just raising an exception. Because the thread is still running, the variables and stack trace may hold misleading states, which makes debugging much more difficult.
I believe we all like to discover the bugs in the early stage of development and offer a reliable and stable application to our customers. Should we stop doing that because there is no valid use case for the tool we need to use?
There is always a valid use case for something. If I am wrong, please enlight me.
For me it seems a valid destructor. Is it? Should I worry?
It is a bad destructor code.
First, everything bad you have heard about TerminateThread is true. There is no safe way to terminate thread as it may leave the application in unstable state, and you should never use that function unless you want to immediately close the application, too. And in such cases it is better to just exit the process altogether. See: Calling TerminateThread on a Windows thread when app exits
Windows started picking up the really big pieces of TerminateThread garbage on the sidewalk, but it’s still garbage on the sidewalk
Now the history.
Originally, there was no TerminateThread function. The original
designers felt strongly that no such function should exist because
there was no safe way to terminate a thread, and there’s no point
having a function that cannot be called safely. But people screamed
that they needed the TerminateThread function, even though it wasn’t
safe, so the operating system designers caved and added the function
because people demanded it. Of course, those people who insisted that
they needed TerminateThread now regret having been given it.
It’s one of those “Be careful what you wish for” things.
Additionally, destructor raises an exception, which is something Delphi destructors should never ever do. Raising exceptions in destructor (which are not caught and handled within try..except block) will cause irreparable memory leaks in application.
There is a better solution?
Yes. Since, Cleanup method will call fThread.Free which will wait for thread completion and will perform normal thread shutdown there is no need to call TerminateThread.
Instead of forcing thread termination, it would be better to Cancel the thread and give it time to gracefully terminate itself. This also may require calling WaitFor although pumping Windows messages at that point could interfere with other application code.
destructor TBackgroundWorker.Destroy;
begin
if IsWorking then
begin
Cancel;
// WaitFor;
Cleanup(True);
end;
inherited Destroy;
end;
Ultimately, it is not in the domain of component to handle what happens if the thread is still running during shutdown. If there is a need to handle such scenario and prevent shutdown, then this needs to be handled from outside code.
Generally, I would avoid using this component as generalized solutions can create more problems than they are worth. Waiting for a thread by pumping messages is not the greatest design. It may work well in some circumstances and not in others.
It would be better architecture to rely on TThread.WaitFor function. However, TThread.WaitFor is blocking call, so that behavior may not fit well into TBackgroundWorker architecture and desired behavior.
Note: I didn't fully inspect the code of TBackgroundWorker component so there may be other issues that are not covered in this post.
Related
Is this the correct way to free TCriticalSection object created inside the initialization section in Delphi?
initialization
FPoolingCS := TCriticalSection.Create;
finalization
FPoolingCS.Acquire;
FreeAndNil(FPoolingCS);
Should I call the Release method before the Free?
Could the Acquire method throw some exceptions that I need to handle?
This is not the correct way to release critical section for several reasons.
According to documentation EnterCriticalSection function
This function can raise EXCEPTION_POSSIBLE_DEADLOCK if a wait
operation on the critical section times out. The timeout interval is
specified by the following registry value:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
Manager\CriticalSectionTimeout. Do not handle a possible deadlock
exception; instead, debug the application.
If a critical section is deleted while it is still owned, the state of
the threads waiting for ownership of the deleted critical section is
undefined.
While a process is exiting, if a call to EnterCriticalSection would
block, it will instead terminate the process immediately. This may
cause global destructors to not be called.
Calling FPoolingCS.Acquire on Windows platform calls EnterCriticalSection function. So the answer to first question, whether acquiring critical section can raise exception, is yes.
Also according to documentation, you should not try to handle such exceptions, but you have to debug the application, because origin of the problem is in some other code.
But the most notable reason why you should not call Acquire before releasing critical section instance on any platform is that if at that point there are some other threads that are doing some work and are relying on that critical section means your shutdown and cleaning process is completely broken. In other words, if Acquire solves your problem, real issue is in another castle and you haven't really solved anything, you have just slightly changed the dynamics, which may work and may not work, depending on all other code involved.
Calling Release before Free would be meaningless, for the same reason. If there are other involved threads still running, they may acquire the lock before Free is executed.
Just call Free on critical section, or if you like use FreeAndNil that will ultimately crash if your shutdown process is broken. Just remember, threading issues are not consistently reproducible, so absence of a crash still does not mean you have fully bug free code.
This question already has answers here:
Resuming suspended thread in Delphi 2010?
(2 answers)
Closed 6 years ago.
Long ago, when I started working with threads in Delphi, I was making threads start themselves by calling TThread.Resume at the end of their constructor, and still do, like so:
constructor TMyThread.Create(const ASomeParam: String);
begin
inherited Create(True);
try
FSomeParam:= ASomeParam;
//Initialize some stuff here...
finally
Resume;
end;
end;
Since then, Resume has been deprecated in favor to use Start instead. However, Start can only be called from outside the thread, and cannot be called from within the constructor.
I have continued to design my threads using Resume as shown above, although I know it's been deprecated - only because I do not want to have to call Start from outside the thread. I find it a bit messy to have to call:
FMyThread := TMyThread.Create(SomeParamValue);
FMyThread.Start;
Question: What's the reason why this change was made? I mean, what is so wrong about using Resume that they want us to use Start instead?
EDIT After Sedat's answer, I guess this really depends on when, within the constructor, does the thread actually begin executing.
The short and pithy answer is because the authors of the TThread class didn't trust developers to read or to understand the documentation. :)
Suspending and resuming a thread is a legitimate operation for only a very limited number of use cases. In fact, that limited number is essentially "one": Debuggers
Undesirables
The reason it is considered undesirable (to say the least) is that problems can arise if a thread is suspended while (for example) it owns a lock on some other synchronization object such as a mutex or sempahore etc.
These synchronization objects are specifically designed to ensure the safe operation of a thread with respect to other threads accessing shared resources, so interrupting and interfering with these mechanisms is likely to lead to problems.
A debugger needs a facility to directly suspend a thread irrespective of these mechanisms for surprisingly similar reasons.
Consider for example that a breakpoint involves an implicit (or you might even say explicit) "suspend" operation on a thread. If a debugger halts a thread when it reaches a break-point then it must also suspend all other threads in the process precisely because they will otherwise race ahead doing work that could interfere with many of the low level tasks that the debugger might be asked to then do.
The Strong Arm of the Debugger
A debugger cannot "inject" nice, polite synchronization objects and mechanisms to request that these other thread suspend themselves in a co-ordinated fashion with some other thread that has been unceremoniously halted (by a breakpoint). The debugger has no choice but to strong-arm the threads and this is precisely what the Suspend/Resume API's are for.
They are for situations where you need to stop a thread "Right now. Whatever you are doing I don't care, just stop!". And later, to then say "OK, you can carry on now with whatever it was you were doing before, whatever it was.".
Well Behaved Threads Behave Well Toward Each Other
It should be patently obvious that this is not how a well-behaved thread interacts with other threads in normal operation (if it wishes to maintain a state of "normal" operation and not create all sorts of problems). In those normal cases a thread very much does and should care what those other threads are doing and ensure that it doesn't interfere, using appropriate synchronization techniques to co-ordinate with those other threads.
In those cases, the legitimate use case for Resuming a thread is similarly reduced to just one, single mode. Which is, that you have created and initialised a thread that you do not wish to run immediately but to start execution at some later point in time under the control of some other thread.
But once that new thread has been started, subsequent synchronization with other threads must be achieved using those proper synchronization techniques, not the brute force of suspending it.
Start vs Suspend/Resume
Hence it was decided that Suspend/Resume had no real place on a general purpose thread class (people implementing debuggers could still call the Windows API's directly) and instead a more appropriate "Start" mechanism was provided.
Hopefully it should be apparent that even though this Start mechanism employs the exact same API that the deprecated Resume method previously employed, the purpose is quite different.
I know Synchronize must be used in the Execute procedure, but should it be used in Create and Destroy methods too, or is it safe to do whatever I want?
I know Synchronize must be used in the Execute procedure.
That is somewhat vague. You need to use Synchronize when you have code that must execute on the main thread. So the answer to whether or not you will need to use Synchronize depends crucially on what the code under consideration actually does. The question that you must ask yourself, and which is one that only you can answer, is do you have code that must run on the main thread?
As a general rule it would be considered prudent for you not to need to call Synchronize outside the Execute method. If you can find a way to avoid doing so then that would be wise. Remember that the ideal scenario with threads is that they never need to block with Synchronize if at all possible.
You might also wish to consider which thread executes the constructor and destructor.
The constructor Create runs in the thread that calls it. It does not run in the newly created thread. Therefore it is unlikely that you would need to use Synchronize there.
The destructor Destroy runs in the thread that calls it. Typically this is the thread that calls Free on the thread object. And usually that would be called from the same thread that originally created the thread. The common exception to that is a FreeOnTerminate thread which calls Free from the thread.
There is a need to use Synchronize() when the code is executing outside of the context of the main (GUI) thread of the application. Therefore the answer to your question depends on whether the constructor and destructor are called from that thread or not.
If you are unsure you can check that by comparing the result of the Windows API function GetCurrentThreadId() with the variable MainThreadID - if they equal the code executes in the context of the main thread.
Threads that have FreeOnTerminate set will have their destructor called from another thread context, so you would need to use Synchronize() or Queue(). Or you use the termination event the VCL already provides, I believe it is executed in the main thread, but check the documentation for details.
First of all, you don't want to call Synchronize() unnecessarily, because that simply defeats the purpose of using a thread. So the decision should be based on whether: (a) it's possible to encounter race conditions with shared data. (b) you'll be using VCL code which usually has to run on the main thread.
It's unlikely you would need to synchronise in the constructor because TThread instances are usually created from the main thread already. (The exception being if you're creating some TThread's from another child thread.)
NOTE: It won't cause any harm though because Synchronize() already checks if you're on the main thread and will call the synchronised method immediately if you are.
class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord; QueueEvent: Boolean = False);
var
SyncProc: TSyncProc;
SyncProcPtr: PSyncProc;
begin
if GetCurrentThreadID = MainThreadID then
ASyncRec.FMethod
As for the destructor there are 3 usage patterns:
The TThread instances destroys itself.
Another thread (possibly the main thread) can WaitFor the instance to finish, then destroy it.
You can intercept the OnTerminate event. This is fired when the instance is finished, and you could then destroy it.
NOTE: The OnTerminate event will already be synchronised.
procedure TThread.DoTerminate;
begin
if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
end;
Given the above, the only time you might need to synchronise is if the thread self-destructs.
However, I'd advise that you rather avoid putting code into your destructor that might need to be synchronised. If you need some results of a calculation from your thread instance, OnTerminate is the more appropriate place to get this.
To add to what has been said in other answers...
You never need to use Synchronize at all. Synchronize may be useful, however, in the following circumstance:
In the context of your thread you need to execute code that touches objects that have affinity to the main thread.
You require your thread to block until that code has been executed.
Even in that case, there are other ways to achive the same goal, but Synchronize provides a convenient way to satisfy those two needs. If you need only one of those two items, there are better strategies available.
On topic #1, the obvious objects are user interface objects. These are objects that have thread affinity to the main thread simply by virtue of the fact that the main thread is continually reading and writing the properties of those objects (not the least because it needs to paint them to the screen, etc) and it does so at its own convenience. This means that your thread cannot safely access those components with a guarantee that the main thread will not also be accessing or modifying them at the same time. In order to prevent corruption, the thread has to pass the work to the main thread (since the main thread can only do one thing at a time and can't, obviously, interfere with itself). Synchronize simply places the work onto the main thread's queue and waits until the main thread gets around to completing it before returning.
This gets to point #2. Do you need to (or, equally, can you afford to) wait around until the main thread finishes the work? There are three cases and two options.
Yes, you can or must wait. (Synchronize is a good fit)
No, you cannot wait. (Synchronize is not a good fit)
Don't care. (Synchronize is easy, so it's a sensible option)
If you are simply updating a status display that will soon be overwritten anyway and your thread has more pressing issues, then it's probably sensible to just post a message to the main thread and carry on doing things, for example. If your thread is just waiting around doing nothing, mostly, and it's not worth the time to code anything more sophisticated, then Synchronize is just fine, and it can be replaced with something better if needs dictate so in the future.
As others have said, it really depends on what you are doing. The more important question, I think, at least conceptually, is to sort out when you need to worry about concurrency and when you don't. Any time you have more than one thread that requires access to a single resource you need to use some sort of mechanism to coordinate that access to avoid the threads crashing into each other. Synchronize is one of those methods, but it not the least nor the last of them.
How to put the IDispatch::Invoke to a thread and call TerminateThread if it timeouts?
The reason I wanted to do this is because I find that sometimes the Invoke call will go into infinity loop and never return anything and hence the call will just sit there for forever. Hence, I am thinking of putting the Invoke to a thread and terminate the thread when it timeout.
Any advices or references are really appreciated.
Peace
Hi i strongly do not recommend you call TerminateThread for any others things but TerminateThread + IDispatch::Invoke can cause abnormal program termination in good case and more strange program behavior and random crashes in bad one. I think you need chose another way...
I'm looking for a way to debug a rare Delphi 7 critical section (TCriticalSection) hang/deadlock. In this case, if a thread is waiting on a critical section for more than say 10 seconds, I'd like to produce a report with the stack trace of both the thread currently locking the critical section and also the thread that failed to be able to lock the critical section after waiting 10 seconds. It is OK then if an exception is raised or the Application terminates.
I would prefer to continue using critical sections, rather than using other synchronization primitives, if possible, but can switch if necessary (such as to get a timeout feature).
If the tool/method works at runtime outside of the IDE, that is a bonus, since this is hard to reproduce on demand. In the rare case I can duplicate the deadlock inside the IDE, if I try to Pause to start debugging, the IDE just sits there doing nothing, and never gets to a state where I can view threads or call stacks. I can Reset the running program, though.
Update: In this case, I'm only dealing with one critical section and 2 threads, so this likely isn't a lock ordering problem. I believe there is an improper nested attempt to enter the lock across two different threads, which results in deadlock.
You should create and use your own lock object class. It can be implemented using critical sections or mutexes, depending on whether you want to debug this or not.
Creating your own class has an added benefit: You can implement a locking hierarchy and raise an exception when it is violated. Deadlocks happen when locks are not taken in exactly the same order, every time. Assigning a lock level to each lock makes it possible to check that the locks are taken in the correct order. You could store the current lock level in a threadvar, and allow only locks to be taken that have a lower lock level, otherwise you raise an exception. This will catch all violations, even when no deadlock happens, so it should speed up your debugging a lot.
As for getting the stack trace of the threads, there are many questions here on Stack Overflow dealing with this.
Update
You write:
In this case, I'm only dealing with one critical section and 2 threads, so this likely isn't a lock ordering problem. I believe there is an improper nested attempt to enter the lock across two different threads, which results in deadlock.
That can't be the whole story. There's no way to deadlock with two threads and a single critical section alone on Windows, because critical sections can be acquired there recursively by a thread. There has to be another blocking mechanism involved, like for example the SendMessage() call.
But if you really are dealing with two threads only, then one of them has to be the main / VCL / GUI thread. In that case you should be able to use the MadExcept "Main thread freeze checking" feature. It will try to send a message to the main thread, and fail after a customizable time has elapsed without the message being handled. If your main thread is blocking on the critical section, and the other thread is blocking on a message handling call then MadExcept should be able to catch this and give you a stack trace for both threads.
This is not a direct anwer to your question, but something I ran into recently that had me (and a couple of colleagues) stumped for a while.
It was an intermittent thread hang, involving a critical section and once we knew the cause, it was very obvious and gave all of us a "d'oh" moment. However, it did take some serious hunting to find (adding more and more trace logging to pinpoint the offending statement) and that is why I thought I'd mention it.
It also was on a critical section enter. Another thread had indeed acquired that critical section. A dead lock as such did not seem to be the cause, as there was only one critical section involved, so there could be no problems with acquiring locks in a different order. The thread holding the critical section should simply have continued and then released the lock, allowing the other thread to acquire it.
In the end it turned out that the thread holding the lock was ultimately accessing the ItemIndex of a (IIRC) combobox, fairly innocuous it would seem. Unfortunately, getting that ItemIndex is reliant on message processing. And the thread waiting for the lock was the main application thread... (just in case anybody wonders: the main thread does all the message processing...)
We might have thought of this a lot earlier if it had been a little more obvious from the start that the vcl was involved. However, it started in non-ui related code and vcl involvement only became apparent after adding instrumentation (enter - exit tracing) along the call tree and back through all triggered events and their handlers up to the ui code.
Just hope this story will be of help to somebody faced with a mysterious hang.
Use Mutex instead of Critical Section. There is a little difference between mutexes and critical sections - critical sections are more effective while mutexes are more flexible. Your can easily switch between mutexes and critical sections, using for example mutexes in debug version.
for critical section we use:
var
FLock: TRTLCriticalSection;
InitializeCriticalSection(FLock); // create lock
DeleteCriticalSection(FLock); // free lock
EnterCriticalSection(FLock); // acquire lock
LeaveCriticalSection(FLock); // release lock
the same with mutex:
var FLock: THandle;
FLock:= CreateMutex(nil, False, nil); // create lock
CloseHandle(FLock); // free lock
WaitForSingleObject(FLock, Timeout); // acquire lock
ReleaseMutex(FLock); // release lock
You can use timeouts (in milliseconds; 10000 for 10 seconds) with mutexes by implementing acquire lock function like this:
function AcquireLock(Lock: THandle; TimeOut: LongWord): Boolean;
begin
Result:= WaitForSingleObject(Lock, Timeout) = WAIT_OBJECT_0;
end;
You can also use Critical Sections with the TryEnterCriticalSection API instead of EnterCriticalSection.
If you use TryEnterCriticalSection and the lock acquisition fails, the API returns False and you can deal with the failure in any way you see fit, instead of just locking the thread.
Something like
while not TryEnterCriticalSection(fLock) and (additional_checks) do
begin
deal_with_failure();
sleep(500); // wait 500 ms
end;
Do note that Delphi's TCriticalSection uses EnterCriticalSection so unless you tweak that class, you will have to do your own class or you'll have to deal with the Critical Section initialization/deinitialization.
If you want to be able to wait on something with a timeout, you could try replacing your Critical Section with a TEvent signal. You can say to wait on the event, give it a timeout length, and check the result code. If the signal was set, then you can continue. If not, if it timed out, you raise an exception.
At least, that's how I'd do it in D2010. I'm not sure if Delphi 7 has TEvent, but it probably does.