Dependency Resolution with Structure Map and 64bit Multi-Core machines

231 views
Skip to first unread message

AntonyDenyer

unread,
Oct 24, 2011, 7:08:28 AM10/24/11
to OpenRasta
Hi Guys

Any help with this would be much appreciated.

I'm getting some strange behaviour with multi core machines. It only
happens about 1% of the time and all I'm doing is hitting the fairly
standard Status Resource (all be it with a lot of requests, about 1000
per minute).

The container code looks thread safe to me and as far as I can tell
the OpenRasta pipeline should be too.

public class DependencyResolver : IDependencyResolverAccessor
{
public IDependencyResolver Resolver
{
get { return new
StructureMapDependencyResolver(ConfigureContainer()); }
}


public static IContainer ConfigureContainer()
{
var container = new Container();
lock (container)
{
container.Configure(c => c.Scan(s => {//do dependency
stuff }));
}
return container;
}
}
}

It doesn't happen on a 32bit single core machine.
The error is essentially the same (Structure Map 202 can't resolve)
but the object that can't be resolved is different.

Here's an example stack trace:

OpenRasta.DI.DependencyResolutionException: An error occurred while
trying to resolve type IOperationFilter. --->
StructureMap.StructureMapException: StructureMap Exception Code: 202
No Default Instance defined for PluginFamily
OpenRasta.Web.ICommunicationContext, OpenRasta, Version=2.0.3.0,
Culture=neutral, PublicKeyToken=e04bf464d7caae73
- Hide quoted text -
at StructureMap.BuildSession.<.ctor>b__0(Type t)
at StructureMap.Util.Cache`2.get_Item(KEY key)
at StructureMap.BuildSession.CreateInstance(Type pluginType)
at StructureMap.Pipeline.Instance.createRawObject(Type pluginType,
BuildSession session)
at StructureMap.Pipeline.Instance.Build(Type pluginType,
BuildSession session)
at StructureMap.Pipeline.ConstructorInstance.Get[T](String
propertyName, BuildSession session)
at lambda_method(Closure , IArguments )
at
StructureMap.Construction.BuilderCompiler.FuncCompiler`1.<>c__DisplayClass2.<CreateBuilder>b__0(IArguments
args)
at
StructureMap.Construction.InstanceBuilder.BuildInstance(IArguments
args)
at StructureMap.Pipeline.ConstructorInstance.Build(Type pluginType,
BuildSession session, IInstanceBuilder builder)
at StructureMap.Pipeline.Instance.createRawObject(Type pluginType,
BuildSession session)
at StructureMap.Pipeline.Instance.Build(Type pluginType,
BuildSession session)
at StructureMap.Pipeline.ObjectBuilder.Resolve(Type pluginType,
Instance instance, BuildSession session)
at StructureMap.BuildSession.CreateInstance(Type pluginType,
Instance instance)
at StructureMap.BuildSession.CreateInstanceArray(Type pluginType,
Instance[] instances)
at StructureMap.Container.getListOfTypeWithSession[T](BuildSession
session)
at
OpenRasta.DI.StructureMap.StructureMapDependencyResolver.ResolveAllCore[TService]
() in c:\BuildAgent\work\636e974733804e57\src\structuremap
\OpenRasta.DI.StructureMap\StructureMapDependencyResolver.cs:line 57
at OpenRasta.DI.DependencyResolverCore.ResolveAll[TService]() in c:
\BuildAgent\work\636e974733804e57\src\core\OpenRasta\DI
\DependencyResolverCore.cs:line 70
--- End of inner exception stack trace ---
at OpenRasta.DI.DependencyResolverCore.ResolveAll[TService]() in c:
\BuildAgent\work\636e974733804e57\src\core\OpenRasta\DI
\DependencyResolverCore.cs:line 78
at
OpenRasta.Pipeline.Contributors.AbstractOperationProcessing`2.<GetMethods>d__0.MoveNext()
in c:\BuildAgent\work\636e974733804e57\src\core\OpenRasta\Pipeline
\Contributors\AbstractOperationProcessing.cs:line 57
at OpenRasta.FuncExtensions.Chain[T](IEnumerable`1 functions) in c:
\BuildAgent\work\636e974733804e57\src\core\OpenRasta
\FuncExtensions.cs:line 14
at
OpenRasta.Pipeline.Contributors.AbstractOperationProcessing`2.ProcessOperations(IEnumerable`1
operations) in c:\BuildAgent\work\636e974733804e57\src\core\OpenRasta
\Pipeline\Contributors\AbstractOperationProcessing.cs:line 33
at
OpenRasta.Pipeline.Contributors.AbstractOperationProcessing`2.ProcessOperations(ICommunicationContext
context) in c:\BuildAgent\work\636e974733804e57\src\core\OpenRasta
\Pipeline\Contributors\AbstractOperationProcessing.cs:line 24
at
OpenRasta.Pipeline.PipelineRunner.ExecuteContributor(ICommunicationContext
context, ContributorCall call) in c:\BuildAgent\work
\636e974733804e57\src\core\OpenRasta\Pipeline\PipelineRunner.cs:line
192
Logger: OpenRasta.Pipeline.PipelineRunner

Sebastien Lambla

unread,
Oct 24, 2011, 7:36:57 AM10/24/11
to open...@googlegroups.com
That is strange indeed. Are you running on IIS or self-hosted?

It may be a threading issue in the structuremap code, as ICommContext (which is what is failing to resolve when building interceptors in your case) ought to be injected when the request is built, and hence before the pipeline executes. That leaves us with one of two possibilities: some code in structuremap is not thread safe in these scenarios, or some code has thread affinity and under load you hit the problem where the asp.net pipeline changes threads in-between execution steps (but that's a thread affinity issue in the SM-OpenRasta integration code).

Can you give me a bit more details about your hosting environment?

Seb
________________________________________
From: open...@googlegroups.com [open...@googlegroups.com] on behalf of AntonyDenyer [antony...@gmail.com]
Sent: 24 October 2011 12:08
To: OpenRasta
Subject: [openrasta] Dependency Resolution with Structure Map and 64bit Multi-Core machines

Antony Denyer

unread,
Oct 24, 2011, 10:53:13 AM10/24/11
to open...@googlegroups.com
We're on IIS 7.0 both locally and in production.
Production is set to run in Integrated on dot 4.0
Local is set to run in Classic on dot 4.0

We found the problem in production and then reproduced it locally.
Locally I'm on Win 2008 server R2 sp1 64 bit core i5
Production is Win 2008 server R2 sp1 64 bit xeon dual core 2.2gig

Not sure what's going on, we definitely only have one resolver
instance. But as you say the stuff added per request can't be
resolved.

Sebastien Lambla

unread,
Oct 24, 2011, 11:39:21 AM10/24/11
to open...@googlegroups.com
I'll add more tests to it, there's an issue on .net 4 apparently in some circumstances that may be due to IIS changing again how asp.net runs code.

If you had a unit test (or load test or whatever) that shows the problem reliably it'd be very very helpful. Can you open a bug on http://github.com/openrasta/openrasta-hosting-aspnet with a repro case, and I'll move it to the SM repository when it's pushed?

Thanks
________________________________________
From: open...@googlegroups.com [open...@googlegroups.com] on behalf of Antony Denyer [antony...@gmail.com]
Sent: 24 October 2011 15:53
To: open...@googlegroups.com
Subject: Re: [openrasta] Dependency Resolution with Structure Map and 64bit Multi-Core machines

Neil Mosafi

unread,
Oct 24, 2011, 12:12:26 PM10/24/11
to open...@googlegroups.com
I think it sounds like the same issue mentioned here http://stackoverflow.com/questions/5163606/openrasta-di-perrequest-lifetime-problem

Graham Hay

unread,
Oct 24, 2011, 12:22:45 PM10/24/11
to open...@googlegroups.com
I'm struggling to find any explanation of how this is possible though.

OR registers the communication context per request, which SM puts in the current http context. Then later, whether the same thread or another, we get something out of the current http context. But it's not there.

Surely ASP.NET guarantees that the http context will be correct for the request, whatever thread you're on?

On 24 October 2011 16:39, Sebastien Lambla <s...@serialseb.com> wrote:

Sebastien Lambla

unread,
Oct 24, 2011, 2:28:32 PM10/24/11
to open...@googlegroups.com
OpenRasta uses a separate context store so it can use the same IoC code in and out of asp.net, otherwise things would break down.

I agree with you that it makes very very little sense that those things wouldn't get registered properly, and the only thing I can think of is that, so far not reproduced, issues some people see with .net 4 and IIS7+ where OR doesn't get called when it should.

Neil, if you do have a repro, please send, as it works on my machine (oh dear)....

From: open...@googlegroups.com [open...@googlegroups.com] on behalf of Graham Hay [graha...@7digital.com]
Sent: 24 October 2011 17:22

Neil Mosafi

unread,
Oct 24, 2011, 2:43:55 PM10/24/11
to open...@googlegroups.com
LOL I thought you'd seen it. I will make one and email it over to you unless you want me to upload somewhere else

Neil Mosafi

unread,
Oct 24, 2011, 3:24:24 PM10/24/11
to open...@googlegroups.com
Sent one over, hope it doesn't work on your machine :-)

Sebastien Lambla

unread,
Oct 25, 2011, 3:47:09 AM10/25/11
to open...@googlegroups.com
 I'll take a look later today

From: open...@googlegroups.com [open...@googlegroups.com] on behalf of Neil Mosafi [nmo...@gmail.com]
Sent: 24 October 2011 20:24

Graham Hay

unread,
Oct 25, 2011, 5:17:12 AM10/25/11
to open...@googlegroups.com
OK, but SM doesn't know anything about your IContextStore. It goes direct to HttpContext.Current(.Items).

I could change the resolver to work in the same way as your internal one, but I can't really see what difference that would make.

On 24 October 2011 19:28, Sebastien Lambla <s...@serialseb.com> wrote:

Sebastien Lambla

unread,
Oct 25, 2011, 7:04:26 AM10/25/11
to open...@googlegroups.com
There's actually tests that make sure things go in the context store from the DI container, if thats broken things will go awry.

The reason is really simple, when you change hosting environment you don't want to be reconfiguring your container for it, otherwise configuration and dependencies break or you have to special-case your code based on your environment. This is why IContextStore exists and it's a requirement that it's in use for container layers.

For 3.0 I'm going to replace the context store by enforcing that containers need to support nested containers, it will then be fully under OR's control, that'll also help with the in-memory nested requests that currently are broken. The alternative is to enrich the IContextStore so we could generate new contexts behind the scene, but i'd rather that solution was done on a per-container basis for those that don't support nested containers properly (and I don't know any container that doesn't support that).

Sent: 25 October 2011 10:17

Graham Hay

unread,
Oct 25, 2011, 7:19:52 AM10/25/11
to open...@googlegroups.com
+1 for nested containers. I'll have a look at the tests.

Neil Mosafi

unread,
Oct 28, 2011, 1:30:01 PM10/28/11
to open...@googlegroups.com
Did the repro work? Any ideas?

On 24 October 2011 19:28, Sebastien Lambla <s...@serialseb.com> wrote:

Sebastien Lambla

unread,
Oct 28, 2011, 1:36:08 PM10/28/11
to open...@googlegroups.com
 No time. It's scheduled for Sunday.

If in the meantime you find the bug and can submit a patch request, you'll get a fix even faster. And if you want to pay for per-fix intervention on the codebase, you got a guaranteed 24 hours analysis and 72 hours fix, at a cost.  :-P

From: open...@googlegroups.com [open...@googlegroups.com] on behalf of Neil Mosafi [nmo...@gmail.com]
Sent: 28 October 2011 18:30

Neil Mosafi

unread,
Oct 28, 2011, 1:44:34 PM10/28/11
to open...@googlegroups.com
LOL I'm not rushing you, was just wondering if my repro did the trick really or if it still worked on your machine

Antony Denyer

unread,
Oct 29, 2011, 5:03:23 AM10/29/11
to open...@googlegroups.com

Hi Neil

I could only reproduce the problem when using casini.

I take it that's not the case for you?

Reply all
Reply to author
Forward
0 new messages