WeakAction, or delegates with a weak reference to their target

Abstract: Thoughts on implementing an Action-type delegate that holds only a weak reference to the target object.

Background

I recently started evaluating MVVM libraries for my client’s project. Though I often share parts of my own unpublished library with a client I had inherited this project and it already had it’s share of commonly-used MVVM types. What it lacked, and I added, was a quickie "message bus" implementation. Not the distributed, enterprise-class sort of message bus, but an intra-app messaging service that decouples senders from receivers. It’s the message bus that I really wanted to replace with a more robust, tested version that must surely already exist in one of the established MVVM libraries.

As luck would have it the first library I downloaded touted a messaging service but, as is too often the case, you get what you pay for. After perusing the code for a bit I could see that the messaging functionality wasn’t thread-safe, a feature I require. My app is a multi-threaded WPF app with both managed and native threads and takes pains to keep work off the UI thread in order to achieve smooth and somewhat real-time rendering of data. Wrapping the library’s messaging code for synchronization would be easy, but it doesn’t feel like fine enough granularity of locking for good performance.

Weak Action is Weak

Another driver in looking for an established library is that my quickie message bus implementation holds references to subscribed listeners. Not really a problem unless a listener fails to unsubscribe, in this case the listener will never be garbage collected. I consider that an undesirable situation. So I took a look at the above library’s implementation of a weak action; I quickly saw that this code used not a weak reference but a strong reference; it suffered the very problem it purported to fix. FYI, I did verify that the problem is known to the library’s author.

Now, at this time I haven’t finished evaluating libraries, and this was a bit of a rough start. Maybe I’ll just set aside some time to come up with a solution myself. Like… now.

An Elegant Solution (maybe…)

The problem I’d like to solve is that Action holds a reference to the target object of non-static delegates, preventing that target from being GC’d. The most elegant solution would allow me to simply replace my use of Action and Action<T> with an implementation that holds only a weak reference to the target. And here it is:

   1: static Action CreateWeakAction(Action action)

   2: {

   3:     if (action == null)

   4:         throw new ArgumentNullException("action");

   5:  

   6:     // If it's a static delegate there's no need to create a weak reference.

   7:     if (action.Target == null)

   8:         return action;

   9:  

  10:     Type type = action.GetType();

  11:     WeakReference targetRef = new WeakReference(action.Target);

  12:     MethodInfo method = action.Method;

  13:  

  14:     return () =>

  15:         {

  16:             // Don't reference 'action' in this lambda expression.

  17:             object target = targetRef.Target;

  18:             if (target == null)

  19:             {

  20:                 // Target was GC'd; don't do anything. (Ick.)

  21:             }

  22:             else

  23:             {

  24:                 Delegate.CreateDelegate(type, target, method).DynamicInvoke();

  25:             }

  26:         };

  27: }

Using CreateWeakAction is pretty easy:

   1: Action action = CreateWeakAction(() => receiver.DoSomething(42));

   2: // Time passes...

   3: action();

Now the target (‘receiver’ in the above example) is free to be collected, but I have a new Action delegate returned from CreateWeakAction that will not be collected unless I release my reference to it. More than that, I have no way of telling whether the delegate I’m holding no longer has a live reference to the target. I could conceivably change my Action to a Func<> that returns an indicator of whether the target was GC’d, but that would require me to actually call the delegate to determine its state. And I would lose the elegant drop-in replacement I was hoping for.

A More Measured Solution

Setting aside my personal desire for elegance solutions, the actual requirements I’m looking to satisfy in my message bus are twofold: 1) don’t hold a reference to the target listener and 2) don’t hold unnecessary objects in the heap. A weak action implementation that satisfies these needs might look something like this:

   1: class WeakAction

   2: {

   3:     public WeakAction(Action action);

   4:     public bool IsTargetAlive { get; }

   5:     public WeakActionInvocationResult Invoke();

   6: }

This would allow me to create an instance of my weak action, invoke it’s behavior when needed, and check whether the target is still alive so that I can cull stale instances from my message bus implementation. And, thanks to an uninterrupted morning at my local coffee joint I have what I wanted. You may note that I’ve made an abstraction for invoking instance delegates; this makes that code more easily reusable for generic implementations (e.g., WeakAction<T>).

   1: internal class WeakAction

   2: {

   3:     private readonly InvocationAgent _instanceAction;

   4:     private readonly Action _staticAction;

   5:  

   6:     public WeakAction(Action action)

   7:     {

   8:         if (action == null)

   9:             throw new ArgumentNullException("action");

  10:  

  11:         if (action.Target != null)

  12:         {

  13:             _instanceAction = new InvocationAgent(action);

  14:         }

  15:         else

  16:         {

  17:             _staticAction = action;

  18:         }

  19:  

  20:         Debug.Assert(_instanceAction == null || _staticAction == null);

  21:         Debug.Assert(!(_instanceAction == null && _staticAction == null));

  22:     }

  23:  

  24:     public bool IsTargetAlive { get { return IsStatic || _instanceAction.IsTargetAlive; } }

  25:  

  26:     private bool IsStatic { get { return _staticAction != null; } }

  27:  

  28:     public WeakActionInvocationResult Invoke()

  29:     {

  30:         if (_instanceAction != null)

  31:             return _instanceAction.Invoke();

  32:  

  33:         _staticAction();

  34:         return WeakActionInvocationResult.Invoked;

  35:     }

  36: }

Note that I’ve made an optimization for static delegates—there’s no need to incur the cost of dynamic invocation in that case because a static delegate has no target, therefore it won’t prevent anything from being GC’d.

Now imagine we have a messaging implementation that needs to track listeners with Action delegates but would rather not keep a reference to listeners forever if they happen not to unsubscribe. We can now create an instance of WeakAction and use it to invoke the listener’s Action when we wish; we can also query the WeakAction on occasion to determine whether it still has a live listener.

Finally here are the missing parts to make it work, the interesting bits. What makes this work is pulling apart the delegate into its component parts, holding the target part with a  weak reference, and reassembling the parts into a delegate only when needed to invoke the original delegate. No reference to the original delegate is held.

   1: internal enum WeakActionInvocationResult

   2: {

   3:     Invoked,

   4:     Collected,

   5: }

   6:  

   7: internal class InvocationAgent

   8: {

   9:     private readonly Type _type;

  10:     private readonly WeakReference _targetRef;

  11:     private readonly MethodInfo _method;

  12:  

  13:     public InvocationAgent(Delegate action)

  14:     {

  15:         Debug.Assert(action.Target != null, "Expected a non-static delegate");

  16:  

  17:         _type = action.GetType();

  18:         _targetRef = new WeakReference(action.Target);

  19:         _method = action.Method;

  20:     }

  21:  

  22:     public bool IsTargetAlive { get { return _targetRef.IsAlive; } }

  23:  

  24:     public WeakActionInvocationResult Invoke(params object[] args)

  25:     {

  26:         object target = _targetRef.Target;

  27:         if (target == null)

  28:             return WeakActionInvocationResult.Collected;

  29:  

  30:         // Don't keep a reference to this delegate.

  31:         Delegate.CreateDelegate(_type, target, _method).DynamicInvoke(args);

  32:         return WeakActionInvocationResult.Invoked;

  33:     }

  34: }

I’ll leave it as an interesting challenge to the reader to implement WeakAction<T>. Here’s what it might look like:

   1: class WeakAction<T>

   2: {

   3:     public WeakAction(Action<T> action);

   4:     public bool IsTargetAlive { get; }

   5:     public WeakActionInvocationResult Invoke(T t);

   6: }

Grab a cup of coffee and have at it. :) Please note: I’ve tested only on the desktop CLR, not Silverlight or Phone, so caveat emptor.

Summer Series – Windows Phone 7 Development

This past week I attended a meeting of the Seattle Silverlight User Group. I’ve attended a number of these in the past and they have been reasonably interesting–largely a result, I think, of easy access to local Microsoft folks who are happy to speak on Silverlight topics. Currently the group is running a series on Windows Phone 7 (WP7) development, the next meeting being the third installment in that series. I attended a WP7 Quickstart event in May and found that this presentation has certainly matured a bit since then, and with the subsequent Beta release there are additional topics to talk about.

What follows are some loose notes I took during the event; this isn’t intended to give you the experience of actually being there. The featured speakers were Pete Blois, a Program Manager on Expression Blend; and Jaime Rodriguez, a Technical Evangelist for Windows Phone.

Notable tidbits that came out during the presentations:

- Pete on the yet-to-appear Pivot and Panorama controls: “Those controls are coming.”
- Jaime on future changes to the platform: “We’re not cutting a lot of things any more.”
- The Bing Maps control will not require a paid license. (Jaime)

Pete Blois
Pete demonstrated Expression Blend for Windows Phone 7. Blend for WP7 has improved quite a bit since the first release, most notable to me being the arrival of a full plate of Behaviors in the asset pane. Also new is the device tab with which you can change the theme (colors), device orientation (landscape and portrait), and whether you want to preview on the emulator or a device.

Pete did some quick demos of implementing page fly-out transitions and addressing orientation changes using Visual State Manager and Fluid Layout.

Blend also has new tooling in the properties pane for the ApplicationBar and its icons. (You’ll find that you can’t access this by selecting the ApplicationBar in the Objects and Timeline pane; you need to select the PhoneApplicationPage (the root element) and find ApplicationBar under Common Properties.) There you can adjust the colors, buttons, menu items and so on. Unfortunately we can’t use x:Name on ApplicationBar or bind to its properties; ApplicationBar is a wrapper over the native OS’ app bar–you can’t bind because it’s not a Silverlight control owned by your app.

Performance of animations can be an issue, and Pete advises using storyboards as well as render and perspective transforms–these happen on the rendering thread (which is a high priority thread). Don’t animate on width, height or layout properties, as these cause invalidation of the layout.

Jaime Rodriguez
Jaime discussed the core Silverlight controls: WP7 has those controls that make sense on the phone. Controls such as DataGrid make less sense in the mobile environment due to the lack of screen real estate. The Beta release is still missing some core controls, and tombstoning should see some improvement, but “We’re not cutting a lot of things any more.”

On the Panorama control (not in the Beta): Panorama should have 3 panels or more of content, otherwise it’s a bit silly to use it; more than 6 or 7 panels is a bit large and unwieldy. Panorama is good for exploring content, and imitates a continuous horizontal landscape that you can explore; it wraps around to the first panel if you swipe past the last one. Interestingly, Panorama does not have an app bar.

On the Pivot control (not in the Beta): it’s basically a slick tab control. Each page in the Pivot is related, but they don’t necessarily need to show the same content.

Bing maps control (not in the Beta): There will be a WP7-specific control for Bing maps. You will need to acquire and app ID to use this (as you do with Bing Maps in general) but you won’t have to pay for using the map. The map will be programmable, support gestures, and ship by RTM.

Jaime demonstrated UI navigation, especially the behavior of the back stack. I won’t get into this, as Yochay Kiriaty has a series on app activation/deactivation, tombstoning and the application execution model here.

Summary
All in all, it was a fairly informative two hours of information. I look forward to the next event on September 1st.

Where Did My Object Go? Part 2

In Part 1 of this article I discussed the possibility of an object instance being collected before a method returns in this scenario: 

    new MyObject().LongRunningMethod();

as well as this scenario: 

    MyObject o = new MyObject();    o.LongRunningMethod();

Here we’ll discuss how this could become a problem. Frankly, it’s pretty easy to cause the problem, but I think it generally involves some ugliness on the part of software design or implementation, largely involving clean-up of fields when the instance is finalized. 

Don’t Try This at Home

I don’t think it’s likely you’ll see a lot of code that does this, but here’s one way to run afoul of your object going way: export a reference to a field that the object cleans up when it’s finalized. You can export the reference, say, by making that field visible through a property. Exposing a field that you’re going to clean up in the finalizer would be an easy way to create a coupling between your object and other (arbitrary) client code that has no knowledge of your object’s life span. 

Call Stack Antics

Another way to invoke the potential problem is to lose your “this” reference on the call stack. The code below manages to lose the “this” reference by passing a field to the helper method rather than allowing the helper to access the field directly via its own “this” reference. When the helper tries to access fs.Length an ObjectDisposedException is thrown. 

Why does this throw? Well, the last live reference to the instance was lost when LongRunningMethod passed _input to Helper. Essentially we’ve again exported the field value from the instance and no longer hold a reference to the instance, allowing the GC to finalize it. Helper is left holding a reference to an object that has been finalized. 

Note: Again, you will not see this behavior in a debug build. When running code marked as “debug” the JITter extends the lifetime of the local object to the end of the method. So you will not see this effect if you’ve compiled with the /debug flag. 

    using System;    using System.IO;

    // Ugliness ensues.
    sealed class MyUglyObject
    {
        public MyUglyObject(string inputPath)
        {
            // Real production code would likely not delete the file when done...
            // ...but this is a sample app.
            _input = new FileStream(Path.GetTempFileName(), FileMode.Open, FileAccess.Read, FileShare.Read);
        }

        ~MyUglyObject()
        {
            if (_input != null)
            {
                _input.Close();
                _input = null;
            }
        }

        public void LongRunningMethod()
        {
            Helper(_input); // Our last reference to 'this' (implicit).
        }

        private void Helper(FileStream fs)
        {
            // A long-running method can easily experience a garbage collection
            // before returning. This one happens for force it to occur.
            GC.Collect();
            GC.WaitForPendingFinalizers();

            // Ka-boom!
            long inputSize = fs.Length;
            // ...
        }

        private FileStream _input;
    }

    class Program
    {
        static void Main(string[] args)
        {
            new MyUglyObject(@"....readme.txt").LongRunningMethod();
        }
    }

Can You See It?

As you can see above it takes a bit of effort to cause the code to blow up. If Helper had used _input.Length instead of taking a parameter the problem would not exist. 

But, what I find a bit creepy about the above code is that if Helper were a static method it would seem respectable: 

    private static void Helper(FileStream fs)
    {
        // A long-running method can easily experience a garbage collection
        // before returning. This one happens for force it to occur.
        GC.Collect();
        GC.WaitForPendingFinalizers();

        // Ka-boom!
        long inputSize = fs.Length;
        // ...
    }

At first glance it now looks like helper is a normal static helper function, as is likely seen in code bases across the world. It doesn’t need a “this” reference, it takes a reference to the object it uses, everything appears fine on the surface. Would you see the “this” reference being lost by the code calling Helper in a code review? I’m not so sure I would have until recently. 

Technorati tags: , , , ,

Where Did My Object Go? Part 1

I ran across this scenario a few months ago and was just reminded of it. It takes a bit of an edge case to make it a problem, but it’s interesting all the same.

There’s a regular idiom in C# in which we call a method on an object instance that we’ve created inline:

    new MyObject().LongRunningMethod();

There assumption may be an assumption that the lifetime of this instance of MyObject extends at least until LongRunningMethod returns, but this isn’t necessarily true. This same assumption is often made about local references to objects:

    MyObject o = new MyObject();    o.LongRunningMethod();

However, in both these cases the object instance may be collected before LongRunningMethod returns.

Does this really happen?

Yes, it can and does. The code below exercises this behavior. When you run it you will see the following output, indicating that the object was collected and finalized before LongRunningMethod returns:

    Using release build
    Inline
    Entering MyObject1.LongRunningMethod().
    Finalizing in ~MyObject1().
    Returning from MyObject1.LongRunningMethod().
    Local reference
    Entering MyObject1.LongRunningMethod().
    Finalizing in ~MyObject1().
    Returning from MyObject1.LongRunningMethod().
Note: You will not see this behavior in a debug build. When running code marked as “debug” the JITter extends the lifetime of the local object to the end of the method. So you will not see this effect if you’ve compiled with the /debug flag.

Note also that this article also assumes we’re using CLR 2.0. Future versions could obviously behavior differently.

Here’s the code. Just drop it into test.cs, run csc test.cs, and execute test.exe.

    using System;

    sealed class MyObject
    {
        ~MyObject()
        {
            Console.WriteLine("Finalizing in ~MyObject1().");
        }

        public void LongRunningMethod()
        {
            Console.WriteLine("Entering MyObject1.LongRunningMethod().");

            // A long-running method can easily experience a garbage collection
            // before returning. This one happens for force it to occur.
            GC.Collect();
            GC.WaitForPendingFinalizers();

            Console.WriteLine("Returning from MyObject1.LongRunningMethod().");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
    #if DEBUG
            string build = "debug";
    #else
            string build = "release";
    #endif
            Console.WriteLine("Using {0} build", build);

            // Try it both ways.

            Console.WriteLine("Inline");
            new MyObject().LongRunningMethod();

            Console.WriteLine();
            Console.WriteLine("Local reference");
            MyObject o = new MyObject();
            o.LongRunningMethod();
        }
    }

Is this a problem?

Generally, I’d say it’s not a problem. Once it has begun execution, LongRunningMethod doesn’t need the original object reference unless it’s making reference to that instance. In that case the GC won’t be able to collect the object.

I’ll discuss how to make it a problem in Part 2 of this article.

Technorati tags: , , ,

C# Anonymous Delegates: Your Stack or Mine?

I want to take a moment to call out what I think is an interesting part of my previous post. Anonymous delegates have an interesting capability. To illustrate, here’s an example:

using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        // 'num' lives on the main thread's stack.
        int num = 0;
        Console.WriteLine("initial num=" + num);

        Thread thread = new Thread(
            delegate()
            {
                // Yet this delegate running on a different thread with
                // it's own stack has access to 'num' as well.
                num = 42;
            });

        thread.Start(); // Start the worker thread.
        thread.Join();  // Wait until the worker thread has finished.

        Console.WriteLine("final num=" + num);
    }
}

 

It’s pretty simple. This program declares and initializes a variable named num, creates and starts a thread that will set num to a different value, then waits for the thread to to complete. In the program’s output we see that num has indeed been set to 42. Here’s the view from the command line:

F:tmp>csc Program.csMicrosoft (R) Visual C# 2005 Compiler version 8.00.50727.42for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.

F:tmp>Program.exeinitial num=0final num=42

 

Okay, that’s as expected. But wait–num lives on the main thread’s stack. How is it that the second thread we’ve created has access to num? num isn’t on the second thread’s stack and it would be a pretty scary thing if the second thread had direct access to the first thread’s stack. All sorts of mayhem could ensue. Providing access to another thread’s stack isn’t exactly the sort of thing we want to happen in managed code.

Chicanery?

As it turns out, though it appears that num is a stack variable in the main method it is not. What we’re experiencing here is a convenience provided by the compiler. Or rather, a trick. A sleight-of-hand. An illusion. num doesn’t actually live on the stack.

In fact, the compiler has made num a field in a compiler generated class so that it can be made available on the heap to the delegate. Here’s the compiled code, courtesy of .NET Reflector:

[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
      // Methods
      public <>c__DisplayClass1() { }
      public void <main>b__0()
      {
          this.num = 0x2a;
      }
      // Fields
      public int num;
}

 

The compiler has given our anonymous delegate method a name: it’s <main>b__0() on this compiler generated class. As a member of this class it obviously has access to num. The illusion is completed by fitting out the Main method so that it has an instance of <>c__DisplayClass1 to use:

private static void Main(string[] args)
{
      Program.<>c__DisplayClass1 class1 = new Program.<>c__DisplayClass1();
      class1.num = 0;
      Console.WriteLine("initial num=" + class1.num);
      Thread thread1 = new Thread(new ThreadStart(class1.b__0));
      thread1.Start();
      thread1.Join();

      Console.WriteLine("final num=" + class1.num);
}

 

So now our Main method has an instance of an object on the heap and can set num to zero since num is a public field on the compiler generated class.

And so, both threads are accessing a variable–not on the stack, but on the heap and accessible to both threads. This helpful behind-the-scenes work by the C# compiler allows us to keep the simplicity of the original code in this example; otherwise, we’d need to implement something like what the compiler has done for us. 

Technorati tags: , ,

[Edit: Fix up formatting.]

Ctrl-C and the .NET console application

I occasionally find myself writing a .NET console application, usually a one-off program used to test code that I’m working on. C# seems well-disposed to writing such programs. For example, I might need an application to listen for messages from another application, whether over sockets, HTTP, or another protocol–the sort of application that would listen for and process incoming messages, continuing forever. It’s the sort of app you simply run from a console window and when you’re done give it the old Ctrl-C. Just hit Ctrl-C or Ctrl-Break on the console window and the application quickly goes away.  

Now, there’s actually something a little sinister going on here… when the app goes away it’s actually exits rather abruptly. There’s no exception thrown, no catch or finally blocks executed–it just (poof) goes away. This isn’t often a problem for me, but if my program modifies some system state while it’s running and needs to revert that state on exit, well, then it is an issue.  

As a simple example consider a program that logs incoming messages. It may have a file open and log messages as they come in. (Or it could alter a registry setting or some other system state to indicate its presence only to revert that setting on exit. Get the idea?) If the app doesn’t terminate normally, how can it clean up after itself?  

First Try: Simple, but broken

To make this a bit more concrete consider this example code. The tricky bit is that when you press Ctrl-C to terminate the program there is no clean up being done. Specifically, the log file isn’t flushed to disk. When I run this program and hit Ctrl-C the log file is left entirely empty. This is because the program hasn’t written enough to the file to flush the file buffer to disk when the program is interrupted. Remember, this program isn’t exiting normally when we use Ctrl-C to interrupt it. In this case, the text “Handling messages.” never appears in the log.  

using System;
using System.IO;
using System.Threading;

namespace Example
{
   class Program
   {
       static void Main(string[] args)
       {
           try
           {
               using (FileStream fs = new FileStream("sample.log", FileMode.Append, FileAccess.Write, FileShare.None))
               using (StreamWriter logWriter = new StreamWriter(fs))
               {
                   Console.WriteLine(
                       "This is the basic program. It doesn't call the clean-up code if you use Ctrl-C, "
                       + "and the log file isn't flushed to disk.");
                   ProcessIncomingMessages(logWriter);
               }
           }
           finally
           {
               Console.WriteLine("Clean-up code invoked.");
           }
       }

       static void ProcessIncomingMessages(TextWriter writer)
       {
           writer.WriteLine("Handling messages.");
           Thread.Sleep(Timeout.Infinite); // Well, pretend it processes messages, okay?
       }
   }
}

   

Console.CancelKeyPress Event

As you might guess there is a way to handle Ctrl-C and Ctrl-Break and it’s the Console‘s CancelKeyPress event. By providing a delegate you can have the runtime notify you when a “cancel key” has been pressed. Here I’ve  

  • Added an anonymous delegate to clean up if Ctrl-C or Ctrl-Break is pressed. As you can see it flushes the writer and closes the file stream.
  • I’ve also moved the fs and logWriter variables outside their using statements to allow access from the finally block.

If you read this code from top-to-bottom it may appear unusual that the code in the CancelKeyPress delegate appears to be using logWriter and fs before either variable is assigned a non-null reference. In fact, what is really happening there is that we’re declaring the code for the delegate in line and handing it off to the CancelKeyPress event–it isn’t executed where its position in the source suggests. In this case it’s only executed when Ctrl-C or Ctrl-Break is pressed.  

        static void Main(string[] args)
       {
           FileStream fs = null;
           StreamWriter logWriter = null;
           try
           {
               Console.WriteLine("This shows use of the cancel handler.");
               Console.CancelKeyPress += delegate
               {
                   Console.WriteLine("Clean-up code invoked in CancelKeyPress handler.");
                   if (logWriter != null)
                       logWriter.Flush();
                   if (fs != null)
                       fs.Close();
                   // The application terminates directly after executing this delegate.
               };

               fs = new FileStream("sample.log", FileMode.Append, FileAccess.Write, FileShare.None);
               logWriter = new StreamWriter(fs);
               ProcessIncomingMessages(logWriter);
           }
           finally
           {
               Console.WriteLine("Clean-up code invoked in finally.");
               if (logWriter != null)
                   logWriter.Flush();
               if (fs != null)
                   fs.Close();
           }
       }

Consolidating Clean Up Code

Here I’ve opted to put the clean-up code in one place rather than duplicating it in the finally block. I’ve declared my own delegate type CleanUpMethod so I have a tidy, parameter-less delegate that I can also call from the finally block.  

       delegate void CleanUpMethod();

       static void Main(string[] args)
       {
           FileStream fs = null;
           StreamWriter logWriter = null;

           string cleanUpLocation = "handler.";
           CleanUpMethod cleanUp =
               delegate
               {
                   Console.WriteLine("Clean-up code invoked in " + cleanUpLocation);
                   if (logWriter != null)
                       logWriter.Flush();
                   if (fs != null)
                       fs.Close();
               };

           try
           {
               Console.WriteLine("This shows use of a single, no-param clean-up handler.");
               Console.CancelKeyPress +=
                   delegate
                   {
                       cleanUp();
                       // The application terminates directly after executing this delegate.
                   };

               fs = new FileStream("sample.log", FileMode.Append, FileAccess.Write, FileShare.None);
               logWriter = new StreamWriter(fs);
               ProcessIncomingMessages(logWriter);
           }
           finally
           {
               cleanUpLocation = "finally.";
               cleanUp();
           }
       }

But why put the clean-up code in a delegate instead of it’s own method? One very helpful aspect of using an anonymous delegate in this example is that the delegate code has access to the local variables in this method. If you use Lutz Roeder’s .NET Reflector to take a look at this program you will see the substantial amount of work that the compiler does for you under the covers in order to provide easy access to the local variables from the delegate method:  

private static void Main(string[] args)
{
     ConsoleCancelEventHandler handler1 = null;
     Program.<>c__DisplayClass3 class1 = new Program.<>c__DisplayClass3();
     class1.fs = null;
     class1.logWriter = null;
     class1.cleanUpLocation = "handler.";
     class1.cleanUp = new Program.CleanUpMethod(class1.b__0);
     try
     {
           Console.WriteLine("This shows use of a single, no-param clean-up handler.");
           if (handler1 == null)
           {
                 handler1 = new ConsoleCancelEventHandler(class1.b__1);
           }
           Console.CancelKeyPress += handler1;
           class1.fs = new FileStream("sample.log", FileMode.Append, FileAccess.Write, FileShare.None);
           class1.logWriter = new StreamWriter(class1.fs);
           Program.ProcessIncomingMessages(class1.logWriter);
     }
     finally
     {
           class1.cleanUpLocation = "finally.";
           class1.cleanUp();
     }
}
I'm pleased the C# compiler does so much work just to make my life easier. :) 
Technorati tags: , ,

Red Flag

A red flag. It’s a warning. An alert. An indication of danger. A notification that something is amiss. There are red flags in the code we work on and the processes we follow. But do we see them? I missed a red flag recently. It happened like this:

I had this curious bug I was trying to fix. The behavior suggested that it was most likely corrupted or uninitialized memory. That’s what intuition borne of experience was telling me, anyway. Randomly timed incorrect behavior in code that was processing a static stream of data. The input data was constant from one run to the next, the bits flowing through the code always the same, but the end result varied pretty much randomly in where and when it failed.

This suggested to me that we were processing someone else’s data or uninitialized data (which is really just someone else’s data from within the same process).

This body of C++ code was unfamiliar to me, so I found myself picking the brains of a coworker who had been around a while. In discussing the bug I found myself looking over his shoulder as he scrolled through some of the code in question, and he commented on a variable assignment that wasn’t used later in the function.

It was one of those pfft moments. “Been there, done that, seen it a million times.” A thoughtless assignment statement that someone typed in but then lost their train of thought. It looked something like this:

void fn()
{
    size_t cbBase;
    void* pvData;

    if (get_value("base", &cbBase, &pvData))
    {
        store_data("base", cbBase, pvData);

        size_t cbExtended;
        void* pvDataExtended;

        if (get_value("extended", &cbExtended, &pvDataExtended))
        {
            store_data("extended", cbExtended, pvDataExtended);
            cbBase = cbExtended;
        }
    }
}

And quickly we moved on to discuss what might really be wrong with the code. And that quickly I’d dismissed the red flag.

In a world where most of the code that I interact with is not my own, where dozens of changes wrought by numerous hands happen over a period of years can I really pass off a small, unexplained assignment like that above as an innocuous error? Any moderately complex code base will transmogrify over the years. Initial errors may indeed be simple coding issues that we wish would have been corrected by code review, but over time source code changes not randomly but with specific intent. And with any luck you have both bug reports and a source code revision system on which you can rely to find that intent.

The red flag, of course, was the meaningless assignment statement. More than a day later as I waded through diffs of check-ins from ages past I ran across the rationale for the assignment. In previous check-in an attempt was made to correct some bad behavior. A previous version of the code looked more like this:

void fn()
{
    size_t cbBase;
    void* pvData;

    if (get_value("base", &cbBase, &pvData))
    {
        store_data("base", cbBase, pvData);

        size_t cbExtended;
        void* pvDataExtended;

        if (get_value("extended", &cbExtended, &pvDataExtended))
        {
            store_data("extended", cbExtended, pvDataExtended);
            cbBase = cbExtended;
        }

        if (cbBase < MINIMUM_EXPECTED_DATA_SIZE)
        {
            backfill_missing_extended_data();
        }
    }
}

Ah, the unexplained assignment was orphaned by a previous check-in. In an effort to correct a particular problem a developer had removed code but left behind an ineffective assignment. Interestingly–partly because I like a tidy ending–the bug the developer was fixing was strongly related to the bug I was pursuing. The original author’s intent for the assignment, it turns out, was probably not

    cbBase = cbExtended;

But

    cbBase += cbExtended;

I reintroduced the missing code and patched up the assignment to find that, very conveniently, my bug was fixed as well. In the end, yes, it was incorrectly initialized data. It just wasn’t where I expected to look.

Funny thing, those red flags. They’re hard to see. Where have you seen them lately? (Or not?)