Matteo Pasini
Matteo Pasini

Reputation: 2022

Correct way to free TCriticalSection object in Delphi

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?

Upvotes: 1

Views: 1009

Answers (1)

Dalija Prasnikar
Dalija Prasnikar

Reputation: 28516

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.

Upvotes: 8

Related Questions