Description
[PrestubMethodFrame] SIGSEGV (signal 11) on Linux when the JIT compiles a method that causes type-loading of Nullable<T> where T is a readonly record struct implementing a recursive generic interface with static abstract members.
Works correctly on Windows with the same SDK/runtime version (10.0.7, commit b16286c228).
Reproduction Steps
Minimal repro project (net10.0, LangVersion preview, Nullable enable):
// Program.cs
var list = new List<MyNullableUser>();
list.Add(new MyNullableUser { UserId = default });
Console.WriteLine("OK");
class MyNullableUser
{
public UserId? UserId { get; set; } // triggers SIGSEGV on Linux
}
public interface IEntityId
{
int ToInt();
}
public interface IEntityId<TSelf> : IEntityId
where TSelf : IEntityId<TSelf>
{
EntityIdValue<TSelf> Value { get; }
static abstract int MaxValue { get; }
static abstract TSelf FromInt(int value);
int IEntityId.ToInt() => Value.Value;
}
public readonly record struct EntityIdValue<TId>
where TId : IEntityId<TId>
{
public int Value { get; }
public EntityIdValue(int value)
{
if (value < 0 || value > TId.MaxValue) // static abstract dispatch
throw new ArgumentOutOfRangeException(nameof(value));
Value = value;
}
}
public readonly record struct UserId(EntityIdValue<UserId> Value) : IEntityId<UserId>
{
public static int MaxValue => 600;
public static UserId FromInt(int value) => new(new EntityIdValue<UserId>(value));
public int CompareTo(UserId other) => Value.Value.CompareTo(other.Value.Value);
}
<!-- JitBugRepro.csproj -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
Run on Linux using the official image:
podman run --rm \
-v $(pwd):/app \
"mcr.microsoft.com/dotnet/sdk:10.0@sha256:8a90a473da5205a16979de99d2fc20975e922c68304f5c79d564e666dc3982fc" \
bash -c "cd /app && dotnet run"
Expected behavior
Program prints OK and exits cleanly.
Actual behavior
Segmentation fault (core dumped)
Stack trace from dotnet-dump (captured from real-world reproduction in a larger application hitting the same pattern):
[PrestubMethodFrame] — method containing type-load of Nullable<UserId>
[PrestubMethodFrame] indicates the CLR JIT crashed while compiling the method for the first time. Signal: 11 (SIGSEGV).
Workaround: Change UserId? → UserId (non-nullable). Application starts correctly on Linux with this change.
Regression?
No response
Known Workarounds
Avoid Nullable<T> where T implements an interface with static abstract members.
Use a non-nullable value type with a sentinel value (e.g. default(UserId) to represent "none").
Configuration
Linux (crashing):
| Property |
Value |
| Container image |
mcr.microsoft.com/dotnet/sdk:10.0 |
| Image digest |
sha256:8a90a473da5205a16979de99d2fc20975e922c68304f5c79d564e666dc3982fc |
| OS |
Ubuntu 24.04 |
| .NET SDK |
10.0.203 (commit c23858a6d8) |
| .NET Runtime |
10.0.7 (commit b16286c228) |
| Architecture |
x64 |
| RID |
linux-x64 |
Windows (working):
| Property |
Value |
| OS |
Windows 11 Pro 10.0.26100 |
| .NET SDK |
10.0.101 (commit fad253f51b) |
| .NET Runtime |
10.0.7 (commit b16286c228) |
| Architecture |
x64 |
| RID |
win-x64 |
Other information
No response
Description
[PrestubMethodFrame]SIGSEGV (signal 11) on Linux when the JIT compiles a method that causes type-loading ofNullable<T>whereTis areadonly record structimplementing a recursive generic interface withstatic abstractmembers.Works correctly on Windows with the same SDK/runtime version (
10.0.7, commitb16286c228).Reproduction Steps
Minimal repro project (
net10.0,LangVersion preview,Nullable enable):Run on Linux using the official image:
Expected behavior
Program prints
OKand exits cleanly.Actual behavior
Stack trace from
dotnet-dump(captured from real-world reproduction in a larger application hitting the same pattern):[PrestubMethodFrame]indicates the CLR JIT crashed while compiling the method for the first time. Signal:11 (SIGSEGV).Workaround: Change
UserId?→UserId(non-nullable). Application starts correctly on Linux with this change.Regression?
No response
Known Workarounds
Avoid
Nullable<T>whereTimplements an interface withstatic abstractmembers.Use a non-nullable value type with a sentinel value (e.g.
default(UserId)to represent "none").Configuration
Linux (crashing):
mcr.microsoft.com/dotnet/sdk:10.0sha256:8a90a473da5205a16979de99d2fc20975e922c68304f5c79d564e666dc3982fc10.0.203(commitc23858a6d8)10.0.7(commitb16286c228)linux-x64Windows (working):
10.0.101(commitfad253f51b)10.0.7(commitb16286c228)win-x64Other information
No response