FatalExecutionEngineError
. Other times the code executed without a problem. It was difficult to establish any pattern in these failures. windbg+SoS revealed nothing beyond the fact that the IL was being generated correctly, and excavations of RedBits/Rotor code did not help much either. I went over the whole mess in my mind while listening to a jazz performance, and realized that the flaw was in my delegate-creation IL code, which went like this:push target object
ldftn
dynamic methodnewobj Procedure..ctor(object, native int)
store new delegate
This code creates a working delegate, but the delegate's internal
_methodBase
field is initially null. The bald function pointer does not work as a GC reference, and if there are no other references to the dynamic method, it is liable to be garbage-collected, and the delegate containing the stale function pointer naturally but silently becomes a nest of nasal demons.Delegate.CreateDelegate
overloads don't fill _methodBase
either. DynamicMethod.CreateDelegate
does fill it explicitly, but it is impossible to get the DynamicMethod
object from its token without calling mscorlib's internal methods. I understand the security reasons behind this decision, but it's damned uncomfortable.The only solution to the problem I have found so far is to call the new delegate's
get_Method()
function to fill _methodBase
and establish a GC-visible reference to the dynamic method. Whew!
Update: reported this issue to Microsoft; they decided to close it as a 'known limitation'. Well, it is known — now :3