This article focuses on Exception Handling in .NET 4.0, specifically on the Corrupted State Exceptions concept introduced in .NET Framework 4.0. It describes the System.Runtime.ExceptionServices namespace in .NET4 that adds the ability to handle corrupted state exceptions. It also portrays the importance of corrupted state Exceptions, how to use and handle them in practical scenarios. It also explains how CLR deals for Corrupted state exceptions, and how to use the HandleProcessCorruptedStateExceptionsAttribute.
The .NET4 Framework's Environment had minor but important changes related to Exceptions. Each and every developer tries to make their code or application fool-proof and ideally would like to produce bug free output, no matter how the actions are performed. The biggest challenge here is "handling the right exception". Instead of handling correct Exception, Developer may be in trap of neither checking the Exception, nor getting the meaningful message. As a Developer we need to think on what happens to our code when everything does not go well. DotNET4's Corrupted State Exceptions exactly does what we have been asking and what we didn't have in the previous Frameworks. Corrupted State Exceptions are introduced to have fewer bugs in the code in order to avoid common mistakes in exception handling.
Types of Exceptions
Before we could discuss more detail on Corrupted State Exceptions, let us discuss and understand what are different types of exceptions and how exception handling works in .NET.
In General Managed Exceptions are of two types in .NET Framework.
- User mode exceptions
- Structured Exception Handling (SEH) Exceptions
User Mode Exceptions will rise due to bad logic in application code. These are raised by the application.
SEH exceptions are a different category from those exceptions raised by program. These exceptions belong to context outside of the application. SEH exceptions denote that the process integrity is negotiated and the application can no longer be considered to be in a stable state. Examples would include access violation, stack overflow, Divided by Zero, Invalid Cast Exception etc.
Exceptions till .Net3.5
CLR always delivered exceptions to managed code as exceptions raised in application. There is no issue in it until code doesn't attempt to handle exceptional conditions that it may not be practically handled. For example, most of the applications might not safely maintain execution after an access violation. The CLR exception handling model will catch these kinds of errors until .NET 3.5. This allows applications to catch any exception at the top of the System.Exception hierarchy and users are trapped by doing it. But this is neither a best practice nor an ideal way of handling errors.
Corrupted State Exceptions (CSEs) in .NET4
Corrupted state exceptions are SEH exceptions that indicate the state of a process has been corrupted. CSEs can be considered as Super Exceptions are caused due to bug in the CLR itself or in some native code for which the managed developer has no control over. These are considered way different from other Exceptions. The CLR4 considers exceptions thrown by native code as corrupted state exceptions. By default, the CLR will not let managed code catch these exceptions and finally blocks will not execute.
For example, consider that the code below an Exception in the
SaveNewFile() method can be raised due to lack of diskspace, invalid filename, access violation or process state is corrupt etc. . But here in this case we are forcing the exception to be an IO exception, meaning there is a misinterpretation in the exception type and the way it is handled.
An access violation is an OS exception (still considered as SEH). It is a different kind of exception than the managed CLR exceptions from System.Exception. Since the exception occurs in unmanaged code, the CLR4 exception system will not deliver it to managed code. So from .NET4 Access violation Exception or Process State is corrupt will not be caught by normal catch block. For example if we are calling some native code that has access violation exception inside it, these will not be caught by a
catch block as CLR4 will not handle these types of Exceptions now. The program will be terminated in such cases.
Here is the list of native Win32 exceptions that are considered CSEs:
There are places where we might want to catch these types of exceptions, specifically in our application's "main" function or when loading add-ins. CSEs are especially suited for weird cases that normally do not happen but deserve attention.
Handling CSEs - Implementation
There might be some rare cases in which we need to handle Corrupted State Exceptions. We can do it using a new attribute called
HandleProcessCorruptedStateExceptions from System.Runtime.ExceptionServices namespace. This is used to log that something went wrong or send a notification via email about these exceptions, without continuing processing.
Import the namespace System.Runtime.ExceptionServices.
The CLR converts most of these to a System.Runtime.InteropServices.SEH Exception object except for EXCEPTION_ACCESS_VIOLATION, which is converted to a System.AccessViolationException object, and EXCEPTION_STACK_OVERFLOW, which is converted to a System.StackOverflowExceptionobject.
Individual managed methods can override the defaults and catch these exceptions by applying the
HandleProcessCorruptedStateExceptions attribute to the method.
[HandleProcessCorruptedStateExceptions] attribute also works for AppDomain Unhandled Exception, so if we use an event handler to log errors at this point, it can also be marked with HandleProcessCorruptedStateExceptions attribute. StackOverflowException, OutOfMemoryException and FatalExecutionEngineException are not considered as CSEs.
Is it possible to recompile the code developed using the Microsoft .NET Framework 3.5 and run it in the same way in the .NET Framework 4.0 without having to update the source? Yes. It is.
CLR 4.0 provides a new entry called legacyCorruptedStateExceptionsPolicy for backward compatibility. The old behavior of catching those Corrupted State Exceptions as in previous versions of CLR can be achieved with the following code.
Assemblies compiled using .NET Framework 3.5 or an earlier version of the runtime will be able to process Corrupted State Exceptions when running on the .NET Framework 4.0 by using an entry
LegacyCorruptedStateExceptionsPolicy=true in the Applications' config File.
We have learnt that the CLR no longer serves corrupted state exceptions that occur in the operating system to be handled by managed code. We need to apply the HandleProcessCorruptedStateExceptions attribute to the method that handles the corrupted state exception in order to catch them by CLR. We may hardly notice the effect of this change often, but it's worth keeping in mind since one of the fundamental ideas of exception handling is changed in .NET4 version. Our code may therefore behave differently than we are expected; hence it's very important to know the fundamental changes. Remember that Exception Handling is a powerful technique that needs to be used wisely and carefully.
Please login to rate or to leave a comment.