Archive for the ‘C#’ Category

C# Excel plugin getting disabled

November 15, 2010

Excel disables a plugin (I’m referring to COM and Automation addins here) in two ways:

1. Hard disable – when the plugin causes the host (Excel) to crash

In this case, the COM addin will be in the disabled list and the user will get a message next time it starts Excel asking whether the user still wants that addin or not.
The way Excel does this is by putting the plugin on a black list before calling the OnConnection method (IDTExtensibility2). If the method crashes the host, next time Excel starts up, it finds the offending plugin in the black list.
If the method returns fine, Excel removes it from the black list.
It’s difficult to crash the host from .net, but not impossible. Most of the disables in .net are however…

2. Soft disable – when the plugin returns a failure HRESULT from OnConnection

In .net that means that an exception escapes from OnConnection. The .net framework converts this into an HRESULT when the method returns.
In order to fix that, you need to look into the following areas:
– catch every exception in OnConnection (duh!)
– look at any members part of your class implementing IDTExtensibility2 (any constructor there which throws will generate this condition)
– also look at any static members that can potentially throw
– look at any problems loading dependent assemblies needed by your assembly (this can also cause this)
– if you haven’t written a wrapper for your plugin, and your plugin runs as the mscoree.dll plugin, then check if other similar plugin haven’t been disabled (Excel disables mscoree which disables all plugins running under that – check the MS website on how to write a wrapper and avoid this problem)

System.Threading.SynchronizationLockException

October 20, 2010

I got this exception a while ago when implementing a simple publisher/consumer scheme with 2 threads in C#. What this exception says is that you’re trying to use some operations without a lock held. In my case it was Monitor.Pulse(object).
These sort of operations conceptually need to be done with the lock on object held, for the same reason old Unix condition variable had to do certain operations with the lock held: to avoid race conditions where one thread can miss the signal and get blocked forever on a synchronization primitive.

So the first really easy way to catch this is check if you hold the lock, if not, easy, just add it.

The other situation is to lock one object and operate on another:

lock(Object1)
{
    if(condition)
    {
        Monitor.Wait(Object2)
    }
}

These scenarios are easy to catch and fix because they throw all the time. But this exception can occur in race conditions where it’s more difficult to catch. Let’s look at the following code:

Thread 1 (publisher):

lock(_queue)
{
     _queue.Add(new_element);
     Monitor.Pulse(_queue);
}

Thread 2 (consumer):

List queue;
lock(_queue)
{
     queue = _queue;
     _queue = new List();
}
ProcessQueue(queue);

The idea here is to try to optimize the way the list of type T is emptied and then processed. In particular, the optimization is that it doesn’t create a copy. The copy can be re-written, without this optimization as:

     queue = new List(_queue);
     _queue.Clear();

This has the problem that it allocates memory and copies data, all with the lock held.

But unfortunately, while the optimization works, it’s not entirely correct, as it created a hidden race condition. To illustrate the race condition, I’ll present it here, step by step, with the code running on both threads interlaced below:

1: Thread2:  lock(_queue) <- acquires lock on _queue
2: Thread1:  lock(_queue) <- lock is held by thread2, so thread1 gets blocked here
3: Thread2:  queue = _queue;
4: Thread2:  _queue = new List();
5: Thread2:  release lock on _queue
6: Thread1:  _queue.Add(new_element);
7: Thread1:  Monitor.Pulse(_queue);

At this step 7, Monitor.Pulse throws a System.Threading.SynchronizationLockException.
The reason is that thread1 acquired a lock on _queue but then thread2 changed the “meaning” of the reference _queue, so when thread1 pulses the _queue, it pulses a different object than the one it acquired the lock on. Thus the exception.

Once the problem is understood, the solution is simple: synchronize on an immutable object. You can create a dummy object and sync on that, rather than the mutable _queue.
Or you can implement the more inefficient version, which doesn’t actually change the object _queue refers to.

PS: To reproduce this relatively consistently, insert a Thread.Sleep(5000) in thread2, right after it acquired the lock.