View Full Version : Multi-Threading Execute throws ArgumentException
jimjxr
10-26-2006, 06:57 AM
Hi,
I wonder if anyone tested HibernateTemplate.Execute (with exposeNativeSession set to false) using multiple threads? I've done a test using my own service and dao layer, the Execute method throws the following exception randomly:
System.ArgumentException: Value does not fall within the expected range.
at Spring.Data.NHibernate.HibernateTemplate.Execute(I HibernateCallback action, Boolean exposeNativeSession) in d:\programming\spring.data.nhibernate-20060816-1346\src\spring\spring.data.nhibernate\data\nhiber nate\hibernatetemplate.cs:line 772
at Spring.Data.NHibernate.HibernateTemplate.Execute(I HibernateCallback action) in d:\programming\spring.data.nhibernate-20060816-1346\src\spring\spring.data.nhibernate\data\nhiber nate\hibernatetemplate.cs:line 709
jimjxr
10-26-2006, 06:59 AM
I did some investigation, the exception is thrown from
catch (Exception ex)
{
// Callback code threw application exception...
throw ex;
}
inside the public object Execute(IHibernateCallback action, bool exposeNativeSession) method, I added a log.Error to print out the real stacktrace, and I got:
System.ArgumentException: Value does not fall within the expected range.
at System.Diagnostics.SymbolStore.SymWriter.OpenMetho d(SymbolToken method)
at System.Reflection.Emit.MethodBuilder.CreateMethodB odyHelper(ILGenerator il)
at System.Reflection.Emit.TypeBuilder.CreateType()
at Spring.Aop.Framework.DynamicProxy.CompositionAopPr oxyTypeBuilder.BuildProxyType() in c:\projects\daily\Spring.Net\src\Spring\Spring.Aop \Aop\Framework\DynamicProxy\CompositionAopProxyTyp eBuilder.cs:line 98
at Spring.Aop.Framework.DynamicProxy.DynamicProxyMana ger.GetCompositionProxy(AdvisedSupport advisedSupport) in c:\projects\daily\Spring.Net\src\Spring\Spring.Aop \Aop\Framework\DynamicProxy\DynamicProxyManager.cs :line 51
at Spring.Aop.Framework.DefaultAopProxyFactory.Create AopProxy(AdvisedSupport advisedSupport) in c:\projects\daily\Spring.Net\src\Spring\Spring.Aop \Aop\Framework\DefaultAopProxyFactory.cs:line 83
at Spring.Aop.Framework.AdvisedSupport.CreateAopProxy () in c:\projects\daily\Spring.Net\src\Spring\Spring.Aop \Aop\Framework\AdvisedSupport.cs:line 1091
at Spring.Aop.Framework.ProxyFactory.GetProxy() in c:\projects\daily\Spring.Net\src\Spring\Spring.Aop \Aop\Framework\ProxyFactory.cs:line 91
at Spring.Data.NHibernate.HibernateTemplate.CreateSes sionProxy(ISession session) in d:\programming\spring.data.nhibernate-20060816-1346\src\spring\spring.data.nhibernate\data\nhiber nate\hibernatetemplate.cs:line 1110
at Spring.Data.NHibernate.HibernateTemplate.Execute(I HibernateCallback action, Boolean exposeNativeSession) in d:\programming\spring.data.nhibernate-20060816-1346\src\spring\spring.data.nhibernate\data\nhiber nate\hibernatetemplate.cs:line 754
jimjxr
10-26-2006, 07:04 AM
I wasn't able to find out why this is happening, it looks like the native method .NET used to emit the method code returned an error, but I couldn't find out what is the error.
One sure thing is, there's something wrong with the session proxy created by HibernateTemplate under multiple threads. If I set ExposeNativeSession to true, then this problem goes away.
Any ideas? Is HibernateTemplate.Execute thread safe?
Mark Pollack
10-26-2006, 02:41 PM
Hi,
Well the intention is for it to be thread safe...as for the reality. Do you think you could attach a minimal code example as that would help to more quickly diagnose the issue. Thanks for the investigation. One quick question, in your first post you say the problem appears when exposeNativeSession is set to true but in the last post you seem to indicate the opposite. I gather that the last post is the correct situation...
Mark
Mark Pollack
10-26-2006, 02:50 PM
Hi,
Can you add syncrhonization code around the method
CreateSessionProxy? We'll investigate the threadsafety of proxyfactory...
Mark
jimjxr
10-26-2006, 03:50 PM
The following code seems to solve the problem:
ISession sessionToExpose = null;
lock(typeof(HibernateTemplate))
{
sessionToExpose = (exposeNativeSession ? session : CreateSessionProxy(session));
}
It's a bit hard to produce a test case since the stuff involved would be too much (it would depend on db table). But if you already have a test case, it's easy to modify it to do multi-threading, I use the following code snippets
public void TestMultiThreadService()
{
DoMultiThreadServiceTest(10);
}
private void DoMultiThreadServiceTest(int numOfThreads)
{
Thread[] threads = new Thread[numOfThreads];
for(int i=0; i<numOfThreads; i++)
threads[i] = new Thread(new ThreadStart(RunTestInThread));
for(int i=0; i<numOfThreads; i++)
threads[i].Start();
for(int i=0; i<numOfThreads; i++)
threads[i].Join();
}
private int numOfTestsInThread = 10;
private void RunTestInThread()
{
for(int i=0; i<numOfTestsInThread; i++)
TestPersonService();
}
Just replace TestPersonService with your service test method and you're all set. Please note this error seems to only happen for service/dao method that is a query.
jimjxr
10-26-2006, 03:53 PM
Also do you forsee any problems if I just set ExposeNativeSession to true in order to avoid this problem? I think the session proxy is only for:
a. Prevent callback code from closing the session
b. Apply some caching stuff
So if I take care not to close the session inside callback, using native session should be fine, right?
Bruno Baia
10-26-2006, 04:27 PM
Hi,
I see that you are using an old version (august 2006).
I've made some changes in Spring.Aop at the same period, have you tried with a recent version ?
Cheers,
Bruno
jimjxr
10-27-2006, 03:08 AM
Tried with latest nightly build 20061025, same error.
Mark Pollack
10-27-2006, 03:37 PM
Hi,
I've added a lock inside CreateSessionProxy until we sort it out at a lower level. I gather you've looked at the implementation of the interceptor, so if you can live without functionality provided by PrepareQuery and PrepareCritera, feel free to use exposeNativeSession = true. By default queries aren't cached and maxResults is unbounded, so unless you've explicitly set these properties on HibernateTemplate the only remaining bit of functionality offered by the session proxy is to apply a transaction timeout.
Mark
Bruno Baia
10-27-2006, 07:57 PM
Hi,
Tried with latest nightly build 20061025, same error.
Thanks.
I'm not able to reproduce your bug :(
Can you try something else for me plz :
Rebuild Spring in a Release configuration mode and try again.
Thanks,
Bruno
jimjxr
11-10-2006, 02:18 PM
Instant email notification is not working, I didn't realize you have replied this thread.
I couldn't do a build on nightly build 20061025, Spring.Data project complains:
1. ErrorCodesFactory is in the project file, but the cs couldn't be found.
2. ICommandTextProvider could not be found.
Did I mess up something?
When I did my test a month ago, I was using the ready to use dll under /bin/net/1.1/debug
Do you have a ready to use test case when you try to reproduce the bug? I can take a look and see if I did something wrong.
Mark Pollack
11-10-2006, 08:59 PM
Hi,
Sorry about that. Give it a whirl with the latest download, the vs.net 2005 project should work just fine. Getting the release mode dlls into the nightly builds in on my todo list...
Mark
Powered by vBulletin® Version 4.1.5 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.