views:

200

answers:

2

I have an old MonoRail/ActiveRecord I've been doing some work too.

Recently I decided to upgrade the application to Castle Trunk & NHibernate 2.1.0.4000 GA and I'm now finding a few issues with running tests:

First off - When using TestDriven.Net to run the integration tests that work against the database, it's crashing TestDriven.Net altogether, or all the tests complete execution, then TestDriven.Net hangs. This never happened prior to the upgrade.

When TestDriven.Net crashes, here's what gets written to the event log:

Fault bucket 1467169527, type 1 Event Name: APPCRASH Response: Not available Cab Id: 0

Problem signature: P1: ProcessInvocation86.exe P2: 2.22.2468.0 P3: 4a26845c P4: KERNELBASE.dll P5: 6.1.7600.16385 P6: 4a5bdbdf P7: e053534f P8: 0000b727 P9: P10:

Second thing - Exceptions are being logged when proxy classes are being Finalize()'d, as below - it seems to be once this is logged a couple of times, that is when TestDriven.Net crashes.

Here's the stack trace for the exception:

NHibernate.LazyInitializationException:     
Initializing[MyApp.Core.Models.TestExecutionPackage#15d9eb96-faf0-4b4b-9c5c-9cd400065430]-Could not initialize proxy - no Session.
  at NHibernate.Proxy.AbstractLazyInitializer.Initialize()
  at NHibernate.Proxy.AbstractLazyInitializer.GetImplementation()
  at NHibernate.ByteCode.Castle.LazyInitializer.Intercept(IInvocation invocation)
  at Castle.DynamicProxy.AbstractInvocation.Proceed()
  at Castle.Proxies.TestExecutionPackageProxy.Finalize()

The same behaviour will also crash MsBuild on our CI Server.

What's really odd is that in theory exceptions thrown in Finalize() should be swallowed as per the MSDN docs:

http://msdn.microsoft.com/en-us/library/system.object.finalize%28VS.71%29.aspx

If Finalize or an override of Finalize throws an exception, the runtime ignores the exception, terminates that Finalize method, and continues the finalization process.

Thoughts anyone?

A: 

Never quite got to the bottom of this issue, but I did end up implementing a rather rudimentary work around by creating my own LazyInitializer implementation, where I check for the Finalize method upon invoke, as shown below:

/// <summary>
/// Invoke the actual Property/Method using the Proxy or instantiate the actual
/// object and use it when the Proxy can't handle the method. 
/// </summary>
/// <param name="invocation">The <see cref="IInvocation"/> from the generated Castle.DynamicProxy.</param>
public virtual void Intercept(IInvocation invocation)
{
  try
  {
    if (invocation.Method.Name == "Finalize")
    {
      return;
    }
    if (_constructed)
    {
      // let the generic LazyInitializer figure out if this can be handled
      // with the proxy or if the real class needs to be initialized
      invocation.ReturnValue = base.Invoke(invocation.Method, invocation.Arguments, invocation.Proxy);

      // the base LazyInitializer could not handle it so we need to Invoke
      // the method/property against the real class
      if (invocation.ReturnValue == InvokeImplementation)
      {
        invocation.ReturnValue = invocation.Method.Invoke(GetImplementation(), invocation.Arguments);
        return;
      }
      else
      {
        return;
      }
    }
    else
    {
      // TODO: Find out equivalent to CGLIB's 'method.invokeSuper'.
      return;
    }
  }
  catch (TargetInvocationException tie)
  {
    // Propagate the inner exception so that the proxy throws the same exception as
    // the real object would 
    Exception_InternalPreserveStackTrace.Invoke(tie.InnerException, new Object[] { });
    throw tie.InnerException;
  }
}
Bittercoder
A: 

I had the same problem when a I migrated to 2.1.2 version of NHibernate. I've changed Castle for LinFu Proxy and then everything worked fine for me. Hope this Helps.

Marclei