-
Notifications
You must be signed in to change notification settings - Fork 508
Npgsql causes compilation to fail or infinite loop #6052
Comments
Ouch... Any idea on what Npgsql may be doing to trigger this? How does corert "discover" a type such as |
@roji We already have the same issue in our repo (npgsql/npgsql#1861) and it's not Npgsql related. |
Right, I thought this sounded familiar... I'm still wondering if there's any weird/specific Npgsql code that's triggering this issue (even if it's a UWP / cortrt issue). Will close npgsql/npgsql#2040 at least for now but will watch this issue. If there's any questionable code on Npgsql's side please let me know and I'll take a look. |
Yeah, this is generic recursion. What's happening is pretty much this: class Program
{
struct Gen<T>
{
private T Val1;
private T Val2;
}
static void Recurse<T>(int x)
{
if (x != 0)
Recurse<Gen<T>>(x - 1);
}
static void Main()
{
Recurse<int>(3);
}
} If we're in an environment that has a JIT, we'll end up just-in-time compiling method But an AOT compiler is pretty much screwed. Since in general we can't prove how many times the instantiation will happen, it will end up compiling forever, or until it runs out of memory/stack/or What the compiler needs to do is:
The UWP AOT compiler is a bit more mature and we actually fixed this in .NET Native in our 2.1 release. The fix should be available in version 6.1.5 of the |
I actually wrote a regression test for the specific case of recursion in npgsql when we were doing the fix in .NET Native for UWP apps. The pattern is of course way more convoluted. If you can break the recursion there, it would fix the CoreRT compiler issue. #pragma warning disable 169
struct SqlRange<T>
{
private T Value1;
private T Value2;
}
class ChunkingTypeHandler<T> : TypeHandler<T>
{
}
class RangeHandler<T> : ChunkingTypeHandler<SqlRange<T>>
{
public RangeHandler()
{
new TypeHandler<T>().ToString();
}
}
class TypeHandler
{
public virtual void CreateRangeHandler() { }
}
class TypeHandler<T> : TypeHandler
{
public override void CreateRangeHandler()
{
new RangeHandler<T>().ToString();
}
}
internal class Program
{
private static void Main(string[] args)
{
new TypeHandler<bool>().CreateRangeHandler();
}
} |
Ok, I'll try to take a look on the Npgsql side, maybe the type hierarchy can be factored to avoid this. |
FYI have just submitted PR npgsql/npgsql#2042 which refactors Npgsql's internal type hierarchy to avoid this. @benaadams (or @MichalStrehovsky), can you please test nupkg 4.1.0-ci.1111+sha.8a9e6c98b from Npgsql's unstable myget feed and confirm that the issue is gone? |
@benaadams I've merged npgsql/npgsql#2060 to fix the issue, but you need to write a rd.xml file yourself to use Npgsql, since we use reflection in the connection string builder and other places too. Later we will provide it from the box. |
@YohDeadfall @roji Thank you for making the fix! We'll keep tracking the issue with infinite generic expansion for CoreRT in #363, but I think we can close this now. |
Npgsql 4.0.1 https://www.nuget.org/packages/Npgsql/ and using the
NpgsqlFactory.Instance
property causes compilation to failSeems to be some type recursion?
Including it in the rd.xml
Instead seems like it infinite loops the compiler causing ever growing memory usage (killed it when if hit 5GB)
The text was updated successfully, but these errors were encountered: