[Mono-dev] Assertion failures when using Moq on Linux/ARM

Weeble clockworksaint at gmail.com
Mon Feb 7 07:09:15 EST 2011


(I previously posted a more brief summary of this problem to
mono-list, but I gather this may be a more relevant place to ask.)

I'm currently running Mono 2.6.7 on an ARM box (a Sheevaplug) running
Linux. When I try to run unit tests that work on Windows-x86 with
Microsoft's CLR and on Linux-x86 with Mono, they fail often (but not
always) with an assertion:

thunk failed for 0x40368c80 from 0x4f2a20d8
ERROR:mini-arm.c:2579:handle_thunk: assertion failed: (pdata.found == 1)
Stacktrace:

 at (wrapper managed-to-native)
System.Delegate.CreateDelegate_internal
(System.Type,object,System.Reflection.MethodInfo,bool) <0xffffffff>
 at System.Delegate.CreateDelegate
(System.Type,object,System.Reflection.MethodInfo,bool) <0x006c0>
 at System.Delegate.CreateDelegate
(System.Type,object,System.Reflection.MethodInfo) <0x0002f>
 at System.Reflection.Emit.DynamicMethod.CreateDelegate
(System.Type,object) <0x0003f>
 at System.Linq.Expressions.EmitContext.CreateDelegate
(System.Runtime.CompilerServices.ExecutionScope) <0x0003f>
 at System.Linq.Expressions.CompilationContext.CreateDelegate
(int,System.Runtime.CompilerServices.ExecutionScope) <0x00043>
 at System.Linq.Expressions.CompilationContext.CreateDelegate () <0x0003f>
 at System.Linq.Expressions.LambdaExpression.Compile () <0x00053>
 at System.Linq.Expressions.Expression`1<object>.Compile () <0x0001b>
 at Moq.Mock.GetInterceptor
(System.Linq.Expressions.Expression,Moq.Mock) <0x00073>
 at Moq.Mock.Verify<object>
(Moq.Mock,System.Linq.Expressions.Expression`1<System.Action`1<object>>,Moq.Times,string)
<0x001eb>
 at Moq.Mock`1<object>.Verify
(System.Linq.Expressions.Expression`1<System.Action`1<object>>)
<0x00063>
...

You can see the source of GetInterceptor here:
http://code.google.com/p/moq/source/browse/trunk/Source/Mock.cs#sl_svn751_676

private static Interceptor GetInterceptor(Expression fluentExpression,
Mock mock)
{
       var targetExpression = FluentMockVisitor.Accept(fluentExpression, mock);
       var targetLambda =
Expression.Lambda<Func<Mock>>(Expression.Convert(targetExpression,
typeof(Mock)));
       var targetObject = targetLambda.Compile()();
       return targetObject.Interceptor;
}

The expression getting passed in is fairly trivial. My code does this:

iMockListener.Verify(x => x.SetPropInt(1, 1999));

And then I think Verify extracts the object expression from the method
call which I guess is just the identity function?

Looking at mini-arm.c[1], I think that assertion is saying that it
can't find an appropriate place to create the thunk for a delegate. Is
that right? As far as I can tell it searches some number of thunk
tables (all of them?), checking that the table is in range from
wherever we want to call it from, searching for either an existing
entry in the table to the desired target, or an empty slot where it
can be inserted. It looks like the assertion will occur if all the
thunk tables are either out of range of the source address or full up.
Is that correct? If so, is this not supposed to happen? Under what
circumstances are thunk tables created, and how are they assured to be
in range of the code that calls them?

I'm trying to create a minimal reproduction of this, but at the moment
I haven't gotten very far - I'm still trying to remove a native
library and unsafe code from the equation.

I did discover an email to this list last year[2], in which the
author, Koushik Dutta, discusses what I think is a workaround on
Android to avoid encountering a bug that sounds very similar. He says
that he might try to fix it but that it is quite difficult. Was anyone
since able to fix it?

Best regards,

Weeble.

[1] - https://github.com/mono/mono/blob/master/mono/mini/mini-arm.c#LC2824
[2] - http://lists.ximian.com/pipermail/mono-devel-list/2009-January/030579.html


More information about the Mono-devel-list mailing list