I apologize for this question length, but I think you'll all find it worth it. Before I begin, let me say that I was really trying to produce an isolated console application, but sadly that proved impossible. The bug does not happen in a console app. It doesn't happen in a self-contained ASP.NET app. It only happens when run within IIS 7.5 on Windows 7.
The error seems related to the dynamic language runtime as it involves the combination of a __TransparentProxy
(via WCF) and a dynamic
variable (an int). The line that produces the problem is the invocation of a static method (that happens to contain no method body) passing in both the proxy and the dynamic int.
Once the method is invoked, the w3wp.exe process takes up the entire CPU and starts increasing memory very rapidly (for me about 100 megs per second, though it tapers off presumably due to GC'ing).
To reproduce this error, create a new ASP.NET web site in Visual Studio ("New" | "Project" "C#" | "Web" | "ASP.NET Web Application"). Then create a new site in IIS whose home directory is your new project. (also, give "Everyone" full read/write access to that folder and make sure the app pool is using .NET 4.0) Give the new site a specific port, like 7080. Finally, paste this code into Global.asax.cs:
public class Global : System.Web.HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
dynamic dynamicId = 5;
var serviceUrl = "http://localhost:7182/FooServices.svc";
ChannelFactory factory = new ChannelFactory<IFooServices>(new WSHttpBinding(), new EndpointAddress(serviceUrl));
factory.Open();
IFooServices fooServices = ((ChannelFactory<IFooServices>)factory).CreateChannel();
BlowUpTheProgram(fooServices, dynamicId); // This line hangs
}
[ServiceContract]
public interface IFooServices
{
[OperationContract]
void Bar();
}
public static void BlowUpTheProgram(IFooServices eventServices, int authorMailboxId)
{
}
}
Now access the site in your browser via http://localhost:7080
(or whatever port you chose). Have task manager ready because you'll want to kill the w3wp.exe process after confirming the reported symptoms.
To confirm that the proxy and dynamic are working together to surface this bug, change this line:
dynamic dynamicId = 5;
To:
int dynamicId = 5;
Retry, and you'll notice the problem has gone away and the page loads. Now change it back to dynamic
and then change this line:
IFooServices fooServices = ((ChannelFactory<IFooServices>)factory).CreateChannel();
To:
IFooServices fooServices = null;
Retry, and you'll again notice the problem is gone in this scenario too.
Finally, if I attach the debugger and break all, I can see what it's doing while stuck in this method call. It seems to always show something like:
mscorlib.dll!System.RuntimeMethodHandle.GetDeclaringType(System.IRuntimeMethodInfo method) + 0x2f bytes
mscorlib.dll!System.Reflection.Emit.DynamicResolver.ParentToken(int token) + 0x1f3 bytes
[Native to Managed Transition]
[Managed to Native Transition]
mscorlib.dll!System.Reflection.Emit.DynamicMethod.CreateDelegate(System.Type delegateType, object target) + 0x29 bytes
System.Core.dll!System.Linq.Expressions.Expression>.Compile() + 0xbb bytes
System.Core.dll!System.Runtime.CompilerServices.CallSiteBinder.BindCore>(System.Runtime.CompilerServices.CallSite> site, object[] args) + 0x10a bytes
System.Core.dll!System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid3(System.Runtime.CompilerServices.CallSite site = {System.Runtime.CompilerServices.CallSite>}, WebApplication1.Global arg0 = {ASP.global_asax}, WebApplication1.Global.IFooServices arg1 = {System.Runtime.Remoting.Proxies.__TransparentProxy}, object arg2 = 5) + 0x3f0 bytes
WebApplication1.dll!WebApplication1.Global.Application_Start(object sender = {System.Web.HttpApplicationFactory}, System.EventArgs e = {System.EventArgs}) Line 19 + 0x1b8 bytes C#
For the record, I've tried it on three different machines and was able to repro only on the Windows7/IIS7.5 boxes. On the Windows Server 2008 / IIS7 box there was no problem.
The question is, how do I solve this problem and successfully invoke the method? Also, why is this happening? I'd hate to have to be overly careful about invoking things that will use the DLR because it will make IIS crash.
DontBlowUpTheProgram(fooServices, (int)dynamicId);
– Rockwood