Discovering race conditions using PostSharp

Since the beginning of computer programming one of the problem that always baffled software developers was how to make sure that their code would run properly once threading has been introduce to the application. I’ve been experimenting with PostSharp for a couple of weeks and I thought that perhaps I can use it to discover multi threading issues in my code.

But first - Can you spot the problem with the following class:

public class UniqueIdFactory 
{
    private int counter = 0;

    public int GetNext() 
    {
        var result = counter++;

        return result;
    }
}

Calling GetNext at the same time there is a chance that both thread would receive the same result. Fixing this issue is simple – just add Lock around counter++ or better yet use the Interlocked class. Obviously this is a simple easy to understand and debug example – in a real world project you just can’t go around adding lock to every place you happen change a variable’s value.

What I came up with is a simple attribute that checks that a specific method or methods are not running on multiple threads at the same time.

[Serializable]
public class SingleThreaded : OnMethodBoundaryAspect 
{
    private readonly object _syncObject = new object();
    private int? _executingThreadsId;
    private int _timesCalled;

    public override void OnEntry(MethodExecutionArgs args) 
    {
        var currThreadId = Thread.CurrentThread.ManagedThreadId;
        lock(_syncObject)
        {
            if(_executingThreadsId != null)
            {
                if(_executingThreadsId != currThreadId)
                {
                    var errorMessage = string.Format(
                                                 "Two threads at the same time {0} and {1}", _executingThreadsId, currThreadId);

                    throw new ApplicationException(errorMessage);
                 }

                 _timesCalled++;

            } 
            else
            {
                _executingThreadsId = currThreadId;
                _timesCalled = 1;
            }
        }
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        var currThreadId = Thread.CurrentThread.ManagedThreadId;
        lock(_syncObject)
        {
            if(_executingThreadsId != currThreadId)
                return; // I'm paraniod - so sue me :)

            _timesCalled--;

            if(_timesCalled == 0)
            {
                _executingThreadsId = null;
            }
       }
    }
}

The attribute is simple - Every time a method is called (i.e. OnEntry)

  1. Check if the method is currently running thread (line 10)
  2. Check if it’s a and if it’s not the same thread as the current thread throw exception (line 11 - 15).

And the rest of the code is just plumbing.

To make this attribute even better you can add the following to the attribute class:

[Serializable]
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, AllowMultiple =  true, Inherited = false)]
[MulticastAttributeUsage(MulticastTargets.Method, AllowMultiple = true)]
public class SingleThreaded : OnMethodBoundaryAspect 
{
// code goes here

Now the attribute can be applied to the whole class:

public class UniqueIdFactory 
{
    private int counter = 0;

    [SingleThreaded]
    public int GetNext() 
    {
        var result =  counter++;      

        return result;
    }
}

Although this attribute won’t deterministically catch race conditions – when a race condition will happen in your code – you’ll know about it.

 

Happy coding…



Labels: , , ,