SafeHandle reference counting/finalization problem

38 Views Asked by At

Can't get my mind around the correct usage of safe handles. I've read MSDN documentation, bunch of questions here at SO and even class sources, but the overall picture still doesn't add up.

Firstly, it's stated that safe handles are ment to prevent resources leaking when something bad is happened. Like thread abort, app domain unload, etc. Sort of the cases when finally block may not (and won't) be executed. And this is done via critical finalizers, some concept CLR is aware about and will still invoke them in the aforementions bad cases. Okey, good.

Second, it's stated that safe handles are also ment for prevention of handle recycling attack. Like when the handle may be reclaimed by GC inside p/invoke call. And this is done via pair of AddRef/Release methods that's internally using reference counter. So when we are about to make interop call the reference is incremented. And if GC gets there while we are in the native code, finalizer will check this counter and skip actual handle releasing. Okey, good.

But what happes if thread abort/whatever happens while our app is inside native code? Well, apart from the fact that it's very bad on its own. If I understand everything correctly, no more code will be executed on the thread. So Release method won't decrease reference count. And when critical finalizer will be called for this handle it would still see that someone is using that handle and won't release it. So the initial purpose of not-leaking-at-all-cost is failed.

Where am I wrong here in my reasoning?

1

There are 1 best solutions below

0
On

I'm not expert on the topic, but Thread.Abort() raises a ThreadAbortException that you can catch and ensure your reference count is decreased, or call Thread.ResetAbort() to stop the thread termination. There are also methods like Thread.BeginCriticalRegion that can help control how failures are handled.

But ensuring cleanup is done correctly in the case of aborted threads is at best difficult. And due to problems like this Thread.Abort have been removed in later .net versions. AppDomains have likewise been removed.

The recommendation is to use processes for isolation purposes. That makes the OS responsible for cleanup.