This site uses cookies to deliver our services and to show you relevant ads and job listings.
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and our Terms of Service.
Your use of Stack Overflow’s Products and Services, including the Stack Overflow Network, is subject to these policies and terms.

Join us in building a kind, collaborative learning community via our updated
Code of Conduct.

When MyFn is jitted, it tries to create a ConstrainedRegion from the finally block.

In the case without the ReliabilityContract, no proper ConstrainedRegion could be formed, so a regular code is emitted. The stack overflow exception is thrown on the call to Stackoverflow (after the try block is executed).

In the case with the ReliabilityContract, a ConstrainedRegion could be formed and the stack requirements of methods in the finally block could be lifted into MyFn. The stack overflow exception is now thrown on the call to MyFn (before the try block is ever executed).

Note that this code seems to gracefully fail on a StackOverflow exception, but it actually isn't. If you corrupt the stack by removing the Big-lines, and recursively calling StackOverflow, the OOM is not triggered and the SO exception it not caught. This is a limitation of the PrepareConstrainedRegions (afaik). See also Richter's CLR book: books.google.nl/…
– AbelJan 6 '13 at 15:15

The primary driver for this functionality was to support SQL Servers stringent requirements for integrating the CLR into SQL Server 2005. Probably so that others could use and likely for legal reasons this deep integration was published as a hosting API but the technical requirements were SQL Servers. Remember that in SQL Server, MTBF is measured in months not hours and the process restarting because an unhandled exception happened is completely unacceptable.

This MSDN Magazine article is probably the best one that I've seen describing the technical requirements the constrained execution environment was built for.

The ReliabilityContract is used to decorate your methods to indicate how they operate in terms of potentially asynchronous exceptions (ThreadAbortException, OutOfMemoryException, StackOverflowException). A constrained execution region is defined as a catch or finally (or fault) section of a try block which is immediately preceded by a call to System.Runtime.CompilerServices.RuntimeServices.PrepareConstrainedRegions().

System.Runtime.CompilerServices.RuntimeServices.PrepareConstrainedRegions();
try
{
// this is not constrained
}
catch (Exception e)
{
// this IS a CER
}
finally
{
// this IS ALSO a CER
}

When a ReliabilityContract method is used from within a CER, there are 2 things that happen to it. The method will be pre-prepared by the JIT so that it won't invoke the JIT compiler the first time it's executed which could try to use memory itself and cause it's own exceptions. Also while inside of a CER the runtime promises not to throw a ThreadAbort exception and will wait to throw the exception until after the CER has completed.

So back to your question; I'm still trying to come up with a simple code sample that will directly answer your question. As you may have already guessed though, the simplest sample is going to require quite a lot of code given the asynchronous nature of the problem and will likely be SQLCLR code because that is the environment which will use CERs for the most benefit.

This isn't entirely correct. The CER is also used for SafeHandles to ensure they are closed. This includes any P/Invoke resulting in an OS SafeHandle (GDI+, files, etc). If you start leaking handles in Windows you will run into trouble soon enough.
– JeremyJun 27 '16 at 19:49

Are you running the MSDN sample under the debugger? I do not think it is possible for CER to function when you are executing within the debugger, as the debugger itself changes the nature of execution anyway.

If you build and run the app in optimized release mode, you should be able to see it fail.

While I don't have a concrete example for you, I think you're missing the point of have a try..finally block inside of the methods that guarantee success. The whole point of saying that the method will always succeed means that regards of what (exception) happens during execution, steps will be taken to ensure the data being accessed will be in a valid state when the method returns. Without the try..finally, you wouldn't be ensuring anything, and could mean that only half of the operations you wanted to happen, would happen. Thus, Cer.Success doesn't actually guarantee success, it only states that you as the developer are guaranteeing success.

CER is mainly there to protect hosted CLRs from corrupting state during appdomain teardowns and other exceptional conditions. Hosts such as SQL Server may trigger rude aborts, during rude aborts finally clauses may be interrupted.
– Sam SaffronJul 9 '09 at 3:50

3

To be slightly more explicit, CERs are there to ALLOW the developer the CAPABILITY of writing code that can protect itself from corrupting it's own state in exceptional conditions. There is nothing inherent about a CER that protects the CLR, it just makes it possible to write code that can protect itself. The dirty secret is in CLR 1.0/1.1 it was IMPOSSIBLE to write code that could successfully deal with certain classes of exceptions.
– Peter OehlertAug 28 '09 at 17:08

Despite negative votes, lack of examples for this question proves my point. CERs do not affect code flow, including finally block. They document code so framework can treat it differently. Basically, it translates to "I won't raise asynch exceptions, you don't interrupt me with asynch exceptions". Removing CER won't ever break code, though it might make it less reliable, statistically. It is also rather obvious that CERs can be used for much more than what is currently implemented by runtime.
– imaAug 25 '09 at 14:11

4

CER attributes are NOT only for documentation; when used from within a constrained execution region a method marked with a ReliabilityContract will be prepared before execution by the JIT to be pre-compiled and the memory for the method will be pre-allocated when entering the PrepareConstrainedRegions.
– Peter OehlertAug 28 '09 at 16:40

They ARE documentation. That documentation is read and used by CLR, as I also said - no contradiction here. The point is, "a short sample that breaks, unless the [] is applied" is impossible, nothing breaks without CER attributes. Becomes less reliable - yes, but nothing that can be described as "code breaks".
– imaAug 28 '09 at 19:57

5

not impossible, see the top voted answer
– Sam SaffronAug 28 '09 at 22:09