Sunday, December 06, 2009 12:57 PM bart

Reader Challenge – Fault Handlers in C#

The CLR’s exception handling facilities provide for protected blocks (“try”) one can associate a handler with. There are four kinds of handlers, and exactly one can be associated with a protected block (but nesting can be used to associate multiple handlers with a block of code):

  • A finally handler is executed whenever the block is exited, regardless of whether this happened by normal control flow or an unhandled exception. C# exposes this using the finally keyword.
  • A type-filtered handler handles an exception of a specified class or any of its subclasses. Better known as a “catch block”, C# provides this through its catch keyword.
  • A user-filtered handler runs user-specified code to determine whether the exception should be ignored, handled by the associated handler, or passed on to the next protected block. C# doesn’t expose this, but Visual Basic does by means of its When keyword.
  • A fault handler is executed if an exception occurs, but not on completion of normal control flow. Neither C# nor Visual Basic provide a fault handler language feature.

In this reader challenge, we’re going to focus on fault handlers. Due to their lack of language surface, their effect is often mimicked by using some local state to determine whether the protected block exited gracefully or not:

bool success = false;
try
{
    // Do stuff
    success = true;
}
finally
{
   if (!success)
   {
       // There was a fault. Do something special.
   }
   // Fault or not; this is what finally does.
}

If an exception happens during “Do stuff”, we end up in the finally block and come to conclude success was never set to true. This indicates an error happened, and we should handle the fault case. However, this technique can get a bit tricky when there are different paths exiting the try block: one could return from the enclosing method in various places, requiring the “success = true” code to be sprinkled around. This is exactly what exception handling was designed for: reducing clutter in your code that has to do with error condition/code tracking. So, we’re defeating that purpose.

Today’s challenge is to create a true fault handler in C#, just for the sake of it. This is merely a brain teaser, encouraging readers to find out what happens behind the scenes of compiled C# code. We won’t be addressing certain concerns like non-local return (the case I mentioned above) but will be hunting for the true “fault” handler treasure hidden deeply in the C# compiler’s IL code emitter. The operational specification is the following:

var f = Fault(() => Console.WriteLine("Okay"),
              () => Console.WriteLine("Fault"));
f();
Console.WriteLine();

var g = Fault(() => { throw new Exception("Oops"); },
              () => Console.WriteLine("Fault"));
try
{
    g();
}
catch (Exception ex)
{
    Console.WriteLine(ex);
}

The above should produce the following output:

Okay

Fault
System.Exception: Oops
   at Program.<Main>b__2()
   (I won’t reveal the secrets here yet…)
   at Program.Main()

Action f illustrates the non-exceptional case where the fault handler is not invoked (a finally handler would get invoked). Action g illustrates the exceptional case where the fault handler gets invoked and the exception bubbles up to the catch-block surrounding its invocation.

It’s strictly forbidden to use local state in Fault (or a method it calls) to track the successful execution of the protected block. Therefore, the below is an invalid solution:

static Action Fault(Action protectedBlock, Action faultHandler)
{
    return () =>
    {
        bool success = false;
        try
        {
            protectedBlock();
            success = true;
        }
        finally
        {
            if (!success)
                faultHandler();
        }
    };
}

Moreover, execution of your Fault method should really use a fault handler as encountered in IL code. It should be a fault handler, not mimic one. In addition, you should not go for a solution where you write a Fault method in ILASM by hand and link it as a netmodule in a C# project, using al.exe:

.class private FaultClosure
{
  .field class [System.Core]System.Action protectedBlock
  .field class [System.Core]System.Action faultHandler

  .method void .ctor()
  {
    ldarg.0
    call instance void [mscorlib]System.Object::.ctor()
    ret
  }

  .method void Do()
  {
    .try
    {
      ldarg.0
      ldfld class [System.Core]System.Action Program/FaultClosure::protectedBlock
      callvirt instance void [System.Core]System.Action::Invoke()
      leave.s END
    }
    fault
    {
      ldarg.0
      ldfld class [System.Core]System.Action Program/FaultClosure::faultHandler
      callvirt instance void [System.Core]System.Action::Invoke()
      endfault
    }
    END: ret
  }
}

.method static class [System.Core]System.Action Fault(class [System.Core]System.Action protectedBlock, class [System.Core]System.Action faultHandler)
{
  .locals init (class Program/FaultClosure V_0)
  newobj void Program/FaultClosure::.ctor()
  stloc.0
  ldloc.0
  ldarg.0
  stfld class
[System.Core]System.Action Program/FaultClosure::protectedBlock
  ldloc.0
  ldarg.1
  stfld class
[System.Core]System.Action Program/FaultClosure::faultHandler
  ldloc.0
  ldftn instance void Program/FaultClosure::Do()
  newobj void [System.Core]System.Action::.ctor(object, native int)
  ret
}

Again, this exercise is just for fun with no profit other than brain stimulation. Hint: what C# 2.0 or later feature may cause a “fault” block to be emitted (i.e. if you ildasm a compiled valid C# application, you can find a “fault” keyword)?

Happy holidays!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under: , , ,

Comments

# re: Reader Challenge – Fault Handlers in C#

Sunday, December 06, 2009 8:30 PM by Keith Dahlby

This seems to do the trick:

static Action Fault(Action protectedBlock, Action faultHandler)
{
    return () => Faulter.Fault(protectedBlock, faultHandler);
}

private class Faulter : IDisposable
{
    private Action faultHandler;

    public Faulter(Action faultHandler)
    {
        this.faultHandler = faultHandler;
    }

    public void Dispose()
    {
        faultHandler();
    }

    public static void Fault(Action protectedBlock, Action faultHandler)
    {
        GetFaultEnumerator(protectedBlock, faultHandler).MoveNext();
    }

    private static IEnumerator GetFaultEnumerator(Action protectedBlock, Action faultHandler)
    {
        using (var f = new Faulter(faultHandler))
        {
            protectedBlock();
            yield return false;
        }
    }
}

# re: Reader Challenge – Fault Handlers in C#

Sunday, December 06, 2009 9:18 PM by Artem Govorov

Something like this would work: static Action Fault(Action protectedBlock, Action faultHandler) { return () => TryFault(protectedBlock, faultHandler).GetEnumerator().MoveNext(); } static IEnumerable TryFault(Action protectedBlock, Action faultHandler) { using (new FaultHandler(faultHandler)) { protectedBlock(); yield return new object(); } } public class FaultHandler : IDisposable { private readonly Action _faultHandler; public FaultHandler(Action faultHandler) { _faultHandler = faultHandler; } public void Dispose() { _faultHandler(); } }

# Twitter Trackbacks for Reader Challenge ??? Fault Handlers in C# - B# .NET Blog [bartdesmet.net] on Topsy.com

Pingback from  Twitter Trackbacks for                 Reader Challenge ??? Fault Handlers in C# - B# .NET Blog         [bartdesmet.net]        on Topsy.com

# re: Reader Challenge – Fault Handlers in C#

Sunday, December 06, 2009 10:57 PM by Brad Ford

I don't understand, why wouldn't you do this? try { // Do stuff } catch (Exception ex) // Could be any exception { // There was a fault. Do something special. } finally { // Fault or not; this is what finally does. }

# re: Reader Challenge – Fault Handlers in C#

Sunday, December 06, 2009 11:37 PM by Omer Mor

I'm not sure this will emit a genuine fault handler, but I suppose it passes all other requirements? static Action Fault(Action protectedBlock, Action faultHandler) { return () => { try { protectedBlock(); } catch { faultHandler(); throw; } }; }

# re: Reader Challenge – Fault Handlers in C#

Monday, December 07, 2009 12:24 AM by Vladimir Matveev

Straightforward solution: iterators. C# compiler use fault block when generating implementation of IDisposable.Dispose (if finally blocks exist in source method)

# Reflective Perspective - Chris Alcock &raquo; The Morning Brew #492

Pingback from  Reflective Perspective - Chris Alcock  &raquo; The Morning Brew #492

# re: Reader Challenge – Fault Handlers in C#

Monday, December 07, 2009 12:42 AM by Brad Ford

Sorry if this is a repost, I didn't seem my earlier one... Why not: try { // Do stuff } catch { // There was a fault. Do something special. } finally { // Fault or not; this is what finally does. }

# re: Reader Challenge – Fault Handlers in C#

Monday, December 07, 2009 12:50 AM by Kharos

As you point out, using try..finally is tricky in this scenario because of different paths exiting the block. It is possible to emulate a fault error handler with try..catch, though: try { // Do stuff } catch { // There was a fault. Do something special. throw; } And then optionally: finally { // Fault or not; this is what finally does. } Alternatively, place 'bool exception = false;' before the try and set it to true in the catch block to determine what really happened in the finally block.

# re: Reader Challenge – Fault Handlers in C#

Monday, December 07, 2009 2:46 AM by Dzmitry Huba

Great blog! We can do it with enumerators like this: static Action Fault(Action body, Action faultBody) { return () => { var enumerator = Enumerate(body, faultBody).GetEnumerator(); enumerator.MoveNext(); }; } static IEnumerable Enumerate(Action body, Action faultBody) { try { body(); yield return null; } finally { faultBody(); } }

# re: Reader Challenge – Fault Handlers in C#

Monday, December 07, 2009 4:18 AM by James Hart

Another useful piece of code for this sort of situation was provided by Alois Kraus: geekswithblogs.net/.../121121.aspx

One interesting way to use his ExceptionHelper.InException property is as follows:

public class TransactionContext : IDisposable

{

 private Action _commit, _rollback;

 public TransactionContext(Action commit, Action rollback)

 {

   _commit = commit; _rollback = rollback;

 }

 public void Dispose()

 {

   if (ExceptionHelper.InException) _rollback();

   else _commit();

 }

}

Then you can do:

using (new TransactionContext(SuccessAction, FailureAction))

{

  // code that may fail here...

}

# Interesting Finds: December 7, 2009

Monday, December 07, 2009 4:40 AM by Jason Haley

Interesting Finds: December 7, 2009

# Dew Drop &#8211; December 7, 2009 | Alvin Ashcraft&#039;s Morning Dew

Pingback from  Dew Drop &#8211; December 7, 2009 | Alvin Ashcraft&#039;s Morning Dew

# Twitter Trackbacks for Reader Challenge ??? Fault Handlers in C# - B# .NET Blog [bartdesmet.net] on Topsy.com

Pingback from  Twitter Trackbacks for                 Reader Challenge ??? Fault Handlers in C# - B# .NET Blog         [bartdesmet.net]        on Topsy.com

# Dew Drop &#8211; Experimental Edition &#8211; December 7, 2009 | Alvin Ashcraft&#039;s Morning Dew

Pingback from  Dew Drop &#8211; Experimental Edition &#8211; December 7, 2009 | Alvin Ashcraft&#039;s Morning Dew

# Dew Drop &#8211; Experimental Edition &#8211; December 7, 2009 | Alvin Ashcraft&#039;s Morning Dew

Pingback from  Dew Drop &#8211; Experimental Edition &#8211; December 7, 2009 | Alvin Ashcraft&#039;s Morning Dew

# K1 Speed Seattle Challenge GP Kart Racing Results ??? December 2009 | Racing Automotive Wisdom

Pingback from  K1 Speed Seattle Challenge GP Kart Racing Results ??? December 2009 | Racing Automotive Wisdom

# re: Reader Challenge – Fault Handlers in C#

Tuesday, December 08, 2009 7:36 AM by David Betz

# Social comments and analytics for this post

Tuesday, December 08, 2009 5:42 PM by uberVU - social comments

This post was mentioned on Twitter by dahlbyk: How well do you know C#? Fun challenge by Bart de Smet: Fault Handlers in C#: http://bit.ly/7IpucZ

# re: Reader Challenge – Fault Handlers in C#

Thursday, December 10, 2009 12:53 AM by Jack

Could someone explain to Brad (and me) why this is not good enough: try { // Do stuff } catch (Exception ex) // Could be any exception { // There was a fault. Do something special. } finally { // Fault or not; this is what finally does. }

# re: Reader Challenge – Fault Handlers in C#

Thursday, December 10, 2009 6:08 AM by Ulrik

static Action Fault(Action protectedBlock, Action faultHandler)

       {

           return () =>

           {

               try

               {

                   protectedBlock();

               }

               catch

               {

                   faultHandler();

                   throw;

               }

           };

       }

# re: Reader Challenge – Fault Handlers in C#

Saturday, December 12, 2009 8:49 PM by Ian Griffiths

How do the various enumerator/yield return solutions qualify, given that it is "strictly forbidden to use local state in Fault (or a method it calls)"?

MakeSillyEnum(block, faultHandler).GetEnumerator().MoveNext();

might not explicitly declare any local variables, but we just created a couple of objects here! (Not to mention the fact that MoveNext contains local state, so we fail on the parenthetical requirement too.)

# Interesting Finds: 2009 12.08 ~ 12.14

Sunday, December 13, 2009 6:07 PM by gOODiDEA

.NET RunningASP.NETapplicationsfromaremoteshare

ReaderChallenge

# Reader Challenge ??? Fault Handlers in C# &laquo; Jasper Blog

Monday, December 14, 2009 1:56 AM by Reader Challenge ??? Fault Handlers in C# « Jasper Blog

Pingback from  Reader Challenge ??? Fault Handlers in C# &laquo; Jasper Blog