mercredi 6 janvier 2021

FieldInfo GetValue causes uncatchable exception

One of the objects in my application has an object it uses for thread locking:

class Fred
{
   readonly object ThreadLock = new object();

   void Operation()
   {
      lock(ThreadLock)
         DoStuff();
   }
}

I was writing some code to dump the entire contents (all properties and all fields) of an object and ran into something strange. The dump code includes this:

foreach (var field in item.GetType().GetFields(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
{
   var value = field.GetValue(item);
   Debug.WriteLine("Value for field \"" + field.Name + "\" is " + ((value == null) ? "null" : value.ToString()));
}

When it calls GetValue() for the "ThreadLock" field in my "Fred" class, it crashes immediately and repeatably with a 0xC0000005 exception (not a CLR NullReferenceException), and the exception isn't catchable even though I've got code in my main window to (theoretically) catch unhandled exceptions:

AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;

private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
{
   Debug.WriteLine("*** Unhandled exception!");
}

I tried creating a small test class that had the same structure:

public class TryMe
{
   readonly object ThreadLock = new object();

   public void LockTest()
   {
      lock (ThreadLock)
         Test();
   }

   public void Test()
   {
      FieldInfo field = GetType().GetField("ThreadLock", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
      var v = field.GetValue(this);
      Debug.WriteLine("ThreadLock is " + v);
   }
}

var test = new TryMe();
test.Test();
test.LockTest();

And it works correctly every time (no exceptions).

This looks like a bug in CLR, but since I can't reproduce it in a class small enough to post here, I'm not sure how to proceed.

Are there other functions for catching other types of exceptions? Is there something I can query in the FieldInfo class that indicates "hey, don't even try to access this guy"?





Aucun commentaire:

Enregistrer un commentaire