Finalization and .NET/deterministic or orderly shutdown

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Any chance 2.0 will help with this?

Finalization for .NET really needs the ability to support leaving some
functionality intact until the program actually terminates. There should be
support of exceptions for things like Console.WriteLine to continue working
in a finalizer or outputting to a specific file for example for logging
purposes.

Good program practices typically involve adding code to verify that
everthing got shutdown in an orderly fashion and sometimes the only easy way
to do that withouth completely redesigning a system is to try to handle it in
a more deterministic destruction sort of way (i.e. finalizers). Yes you
could argue if you designed everything to call everything else to dispose all
of your objects on shutdown then you wouldn't need this... the reality is I
haven't seen a .NET project yet that implemented an orderly shutdown of that
nature. So having to CLR features to help with this real world issue, would
help existing and future code. Or a better more deterministic shitdown
process that we can order certain things to shutdown last (Like for example a
singleton file logger class for logging output messages- I really don't want
that finalized until I am done with everything so I can use it for error
diagnostic output).
 
WXS said:
Any chance 2.0 will help with this?

Finalization for .NET really needs the ability to support leaving some
functionality intact until the program actually terminates. There should be
<snip>

Finalizers are not deterministic destruction, quite the opposite.

Instead, the only present way in .NET to handle this is to specifically
call a method on each object to clean it up. The IDisposable pattern is
perfect for this sort of thing.

A finalizer is there for objects that you just leave hanging in the air
without telling them you're finished them. I would say that if you
depend on critical shutdown code to run you should not run it in a
finalizer.

Additionally, a finalizer shouldn't access any objects stored in the
object being finalized, as those objects might've been garbage collected
previously.
 
As I said that is the problem for the most part, have you ever seen a
production worthy application really call dispose and implement a disposable
pattern on every object in the system so these types of things can be done? I
would have to believe the answer is no or very rarely. In that case it seems
..NET is severely lacking in deterministic shutdown to handle these types of
practices.

Let's say for example I hold a unmanaged resource so I use a finalizer to
free it, but there is a problem freeing it. A good programming practice is
to log this to a log file, console output, event log or something. But it
turns out all of those things have been finalized by the point we got here so
I can't output any diagnostics at all.

As I said if it were really realistic for everyone to build their own object
disposal mechanisms you would see more applications doing that. I can't say
I've seen a .NET application of any reasonable size handle shutdown for
everything in such an ordered manner. Given that it seems adding CLR
features or compiler features would be helpful to help resolve this real
world concern.
 
WXS said:
As I said that is the problem for the most part, have you ever seen a
production worthy application really call dispose and implement a
disposable
pattern on every object in the system so these types of things can be
done? I
would have to believe the answer is no or very rarely. In that case it
seems
.NET is severely lacking in deterministic shutdown to handle these types
of
practices.

To be fair, the disposable pattern is only really needed when calling class
contains disposable or unmanaged fields. One place where I've seen problems
is when a class is originally coded without needing IDisposable, all the
code is built up around it, and then the class is changed to require
IDisposable. It's very rare that people actually go back and change all
references to that class to use the IDispose.

One solution to this problem is to do the following for all non-trivial
classes, whether they implement IDisposable or not:
using(new XYZ() as IDisposable) {
}

Doesn't help you with your finalization problem though ;D
Let's say for example I hold a unmanaged resource so I use a finalizer to
free it, but there is a problem freeing it. A good programming practice
is
to log this to a log file, console output, event log or something. But it
turns out all of those things have been finalized by the point we got here
so
I can't output any diagnostics at all.

True, but if your program is in a situation where the entire Framework is
being finalized, then at the very least it's in an AppDomain shutdown. If
it's a Process shutdown then most of your unmanaged resources will generally
be automatically reclaimed by the OS anyway: memory, file handles, GDI
handles and so forth.

Another thing, I haven't tried this, so I don't know, but the documentation
seems to be a bit vague as to whether AppDomain.DomainUnload is called
before or after finalization starts.

I'd say your best solution if this worries you is aggressive use of
IDisposable. Just because others don't always use it properly doesn't mean
you can't.
 
To be fair, the disposable pattern is only really needed when calling class
contains disposable or unmanaged fields.
Agreed. Though there is no other standardized mechanism for shutting down
all of the objects so that validation logic can be done when your object has
been requested to be done with itself.

As you stated also rarely do people go back and redo their code. So then you
would be stuck with wrapping their code to dispose of it. Unfortunately
unless it is a complete solution the finalize issue I brought up still would
be problematic.
True, but if your program is in a situation where the entire Framework is
being finalized, then at the very least it's in an AppDomain shutdown.

The problem is let's say I use Object pools all over my program and I want
to validate everything got returned to the pool before the process
terminates. At application exit/appdomain shutdown if I try to output log
information when that event is received all of the objects may not have had
the opportunity to return themselves to the pool yet so I will get an invalid
diagnostic error from the pool reporting that not all items were returned
yet. AppDomaindshutdown event I am pretty sure comes before finalization,
but that doesn't help in this case. Normally in C++ you would have a global
object singleton (not just a static type) and when that singleton got
destructed due to process exit then I would output my diagnostics.

The alternative in this case is to implement a sort of application phased
shutdown. Make all object or threads that need to subscribe to an event like
the windows system has for windows shutdown but instead this would be for
process shutdown. It would issue QueryProcessShutdown and all of the
subscribers would respond. If all accepted then a ProcessShutdownStarted
message would be sent to say hey everyone shutdown yourself now (giving
threads holding pooled items time to shutdown). When all those listeners
responded then another event ProcessShutdownNow or something like it would be
sent indicating termination procedures should be done now, finish your
cleanup (diagnostic logging, etc.)
Then a final ProcessExiting. I probably will need to implement something
like this to handle this case, but it seems like it should really be part of
the framework to help with proper cleanup, otherwise shutdown just sort of
seems like the swirl in a toilet bowl that doesn't work very well and
everything doesn't get flushed.... yuck!!!
 
WXS said:
Any chance 2.0 will help with this?

C++/CLI (aka VC++ 2005) gives you deterministic destructors AND garbage
collection type finalizers : the destructors are called synchronously as in
unmanaged C++, then the correspnding memory chunk is freed as usual by the
GC. This way, you may use RAII idiom and the like. Unfortuantely, it won't
be available in other langages (another good reason to use C++ IMHO).

Arnaud
MVP - VC
 
True, like you said C++ only it seems unfortunately. Using C# here
(considering switching to C++ for that and other reasons when 2005 is
available). Though even if that were available the problem is depending on
when that was called would you still have access to all finalizable objects
at that point, like Console or a file TextWriter etc since those are
finalizable they may have been finalized prior to getting to your
destructor??? or are you guaranteed that you get destructors before any of
the objects in your class are finalized (I think the answer is no it is not
guaranteed even then, so it may not actually help that scenario).
 
How about having a Disposal class with a static list of WeakReferences. Put
in the following members:
- Register(IDisposable)
- Unregister(IDisposable)

In you ctor you call Register, in your Dispose you call Unregister. Then you
only have to hook an instance of the Disposal class to the AppDomain
shutdown event. When it fires, you walk the WeakReference list calling
Dispose on all undisposed objects. Best of all you don't have to put the
Register/Unregister code in all disposable objects, just in your object
pools (which would obviously have to be IDisposable). That should keep you
from having to have tons of callbacks floating about.
 
Additionally, a finalizer shouldn't access any objects stored in the
object being finalized, as those objects might've been garbage collected
previously.

Slight correction: those objects can't have been garbage collected
previously, but they may have already been finalized.
 
Interesting thought, have used a similar idea for a different scenario.
Unfortunately since the objects could be currently in use by multiple threads
it wouldn't be appropriate to call dispose on the objects that came from the
pool that have not been returned yet since they may be in use by threads that
have not had the time to properly terminate yet. If done in the pool itself,
the same story it's still too early as all threads need to be notified and
given the opportunity to shutdown and return items to the pool before
reporting any issues.

The multistage shutdown I think is the only way barring some type of
framework solution or a way to order the disposal, finalization and garbage
collection of objects.
Another non-posssibility: At any other time the object pool could try to
resurrect itself waiting for things to be officially shutdown, unfortunately
shutdown is special cased in the CLR and forgoes normal garbage collection
procedures and just starts collection objects sometimes irregardless of
finalization.

It's definately not a simple problem which is why Microsoft probably hasn't
done anything about it yet. A staged methodology may help as I said, but
seems like this is a common issue that should be solved at the framework
level so people don't have to try so hard about finding the right way to
implement this.
 
Back
Top