Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it normal to see an interface in a clr callstack?

I have an asp.net application, which is crashing. There is an entry for this in the windows event logs which contains this callstack:

 Exception type: EntryPointNotFoundException 
    Exception message: Entry point was not found.
   at ***.Interfaces.Portal.Repository.ILookup.get_LookupDataCollection()
   at ***.Portal.Repository.Lookup.GetLookUpValue(ILookup lookup, Int32 index)
   at ***.Portal.Repository.Lookup.GetLookUpValue(ILookup lookup)
   at ***.HttpModules.RuntimeHttpModule.SetPageUrlInfoInContext(PageUrlInfo pinfo)
   at ***PortalRuntime.HttpModules.RuntimeHttpModule.BeginRequest(Object sender, EventArgs e)
   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

This happens only on a customer machine and I was not able to reproduce it locally. As you see on the top there is an interface (ILookup, which is really an interface, not a class).

I built a similar sample (method called via an interface). Visual Studio 2015 is smart enough to show this:

ConsoleApplication2.exe!ConsoleApplication2.Lookup.GetLookupId(ConsoleApplication2.ILookup lookup) Line 37  C#

But there you still see the class which implements the method. I also attached to my sample with windbg and printed the stack when the application sits in a breakpoint in the method which was called via the interface: the interface was not on the stack.

Here is my question:

  • Is it normal to see an interface in a clr callstack (especially without the class which implements it)? I think I have never seen such a callstack before… Anyone else? (I mean this in general, regardless of the second part of my question)

  • Here is a very similar question: @Hans Passant in his first comment says “failure to resolve the implementation method for an interface method” and the OP says that “you already answered my question with your first comment”. So is this really the root cause? Does anyone know about a fix for this? Or is it just a special CLR version?

like image 953
gregkalapos Avatar asked Jan 27 '16 13:01

gregkalapos


1 Answers

I can explain why you see this a little bit, it will not be helpful at all to resolve your problem. Nor do I know enough about the way the CLR binds interface methods to their implementation, it is crazily micro-optimized.

At issue is that the jitter must generate the code for the method that contains the interface method call. But it cannot yet know the identity of the object reference. That's not know 100% accurate until the code actually executes. So what it does is allocate a stub, a place holder for the target method. And generates a CALL instruction to that stub. The actual name of that stub method is not relevant, it is going to disappear again when the real target method is resolved.

The stub itself generates a call into the CLR to resolve the target method, now knowing the true identity of the object reference and thus which specific implementation method needs to execute. And patches the machine code so the CALL address is replaced. So the next time the method executes you don't pay the price of the method binding and the call runs at maximum possible warp speed.

As noted, the name of the stub does not matter since it is temporary. Giving it the name of the interface method is very helpful to diagnose a MissingMethodException. Good idea.

The real issue is that the assembly that was loaded is not the one you built your code with. Probably an old one that you forgot to redeploy. Or you just plain forgot to rebuild it when you changed the interface because it is not part of the solution. So it doesn't have an implementation of the interface method, the CLR discovers this very late, when the stub executes. So you see the stub method name on the call stack.

like image 129
Hans Passant Avatar answered Oct 03 '22 21:10

Hans Passant