Hi,

This would appear to be another problem in the same vein as those mentioned 
in 
https://groups.google.com/forum/#!topic/nhibernate-development/l57826ULy-Q 
, but is IMO far more severe since it brings down the entire appdomain 
without affording the application the opportunity to handle the failure.

Basically, any exception thrown in SessionImpl#AfterTransactionCompletion 
will cause the hosting application to crash if it occurs on the timer 
thread used by System.Transactions. This typically occurs due to threading 
issues in the session object. NullReferenceExceptions and 
IndexOutOfRangeExceptions seem to be the usual culprits, triggered by 
collections being modified in a thread-unsafe manner.
Such an exception is likely to indicate corrupt state (out-of-sync caches, 
etc) so it's arguably correct that the appdomain goes down, but the bug 
lies in NHibernate and is not the application's problem. If it cannot be 
fixed properly it must at least be mitigated.

A quick 'fix' might be to put an aggressive try..catch around all the code 
in the TransactionCompleted event handler and delegate to an 
application-specified (optional) handler, providing the option of 
discarding the exception instead of crashing the application. For many use 
cases the corruption will be restricted to the session, which is likely to 
have been torn down already anyway, and this will be a much better 
compromise than crashing.

It's difficult to write a test to reproduce this problem reliably because 
it's thread-related. The only correct solution to the problem appears to 
involve making the session deal correctly with multiple threads, but the 
relevant state is spread across many classes and it's not obvious where the 
synchronisation points should be. Merely making the individual collections 
threadsafe doesn't solve the problem. The NHibernate documentation covers 
usage of the library, but I'm not sure where to find documentation about 
its internal structure; can someone point me to a good source of info?

I need to investigate the session/transaction lifecycle more carefully, but 
it appears that AfterTransactionCompletion can get called twice when a 
distributed transaction terminates: once on the timer thread and once on 
the disposing thread. If it can be guaranteed to fire on the disposing 
thread, possibly we can simply ignore invocations from the timer thread?


Alex Davidson
Bluewire Technologies

-- 

--- 
You received this message because you are subscribed to the Google Groups 
"nhibernate-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to