简体   繁体   中英

.net standard library fails in .net core but not in framework

We have to use api from 3rd party vendor(perforce). Till today, we were able to reference and use that API in .net framework application. But, now we are refactoring our product and of course we decided to use new .net environment, which is .net core 2.2. As, Perforce didn't publish that library for .net core, we decided to port that library to .net standard.

So, in a nutshell we downloaded source code, ported, and added as a reference in .net core project.

So far, so good. A weird thing is that, after some usage of that library we are getting ExecutionEngineException from that library, which triggers Environment.Failfast and terminates application.

One more important information is that library uses another native library(p4bridge.dll).

The exception is so:

FailFast:
A callback was made on a garbage collected delegate of type 'p4netapi!Perforce.P4.P4CallBacks+LogMessageDelegate::Invoke'.

   at Perforce.P4.P4Bridge.RunCommandW(IntPtr, System.String, UInt32, Boolean, IntPtr[], Int32)
   at Perforce.P4.P4Bridge.RunCommandW(IntPtr, System.String, UInt32, Boolean, IntPtr[], Int32)
   at Perforce.P4.P4Server.RunCommand(System.String, UInt32, Boolean, System.String[], Int32)
   at Perforce.P4.P4Command.RunInt(Perforce.P4.StringList)
   at Perforce.P4.P4CommandResult..ctor(Perforce.P4.P4Command, Perforce.P4.StringList)
   at Perforce.P4.P4Command.Run(Perforce.P4.StringList)
   at Perforce.P4.Client.runFileListCmd(System.String, Perforce.P4.Options, System.String, Perforce.P4.FileSpec[])
   at Perforce.P4.Client.SyncFiles(System.Collections.Generic.IList`1<Perforce.P4.FileSpec>, Perforce.P4.Options)

I am already aware of the message related to garbage collected delegate . It seems, at some place pointer to the delegate is passed to unmanaged library and then GC collected it.

We take a look to the source code of that api. And we saw some possible places which can be reason for that error. But, this is just a thought.

While investigating the failure, we created another .net framework application which references to that ported library, and then we didn't came across any error in .net framework.

My questions are:

  1. Is there any difference between .net framework and .net core in terms of garbage collector mechanism ?
  2. How is that possible that, .net framework and .net core reacts to the same library in a different ways?

I thought to post answer to my question as I already solved the issue. And as you are reading my answer now it means that you have faced with a similar problem. First of all, I want to thank to @MarcGravell for his comments and recommend to you to read the comments.

At first, want to summarize answer to the 2nd question:

How is that possible that, .net framework and .net core reacts to the same library in a different ways?

To be honest, from the first glance I was thinking that .net standard library will behave itself in a same manner everywhere. But, of course I was wrong.

Let's start by "defintion" of .Net Standard . .NET Standard is nothing but a specification (think of it as an Interface) , it just only declares what types and APIs are exposed by a specific platform depending on is version.

If you will take a look, you will see that your standard library references the .NET Standard SDK that contains a netstandard.dll containing the APIs or, to better say, the contract , we can use from within the library project. If you will take a look, to the your standard library with Ildasm.exe , you will see that it is using .netstandard.dll .

在此处输入图片说明

And let's check how it is used by our core and framework apps. And in core it works better than framework.

I am always a fan of diagrams:

在此处输入图片说明

As you see in the diagram, both core and framework apps reference their own netstandard.dll . And those libraries are built based on the type forwarding concept. For core apps, BCL types are provided by System.Runtime.dll , while in case of framework apps BCL types are provided by mscorlib.dll . So, two different implementations .

For example, here is the IL code of .netstandard library which will be used by core apps:

在此处输入图片说明

Read more about type forwarding from msdn .

Source of details about .NET Standard .


And now a bit regarding to my first question:

Is there any difference between .net framework and .net core in terms of garbage collector mechanism?

Actually it must not be surprise that Microsoft continues to evolve GC mechanism.


And now how I solved the issue:

Good thing was that library which I ported to standard was open source. I investigated the issue, and in a nutshell they are passing delegate pointer to the unmanaged library. And that unmanaged library saves the pointer and tries to use it during some lifetime which is longer that the lifetime of that pointer. Actually, the interesting point is that framework GC is not collecting that delegate somehow and that's why no exception in framework side. But, in case of core GC collects that delegate and creates reason to the failure. I did change the way how I set that field and it works now. I declared that field as static and initialize it inside static constructor, so lifetime of that delegate is as long as app lifetime.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM