Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception in clrjit.dll when using .NET 9.0 #113369

Open
melfon opened this issue Mar 11, 2025 · 13 comments
Open

Exception in clrjit.dll when using .NET 9.0 #113369

melfon opened this issue Mar 11, 2025 · 13 comments
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI untriaged New issue has not been triaged by the area owner

Comments

@melfon
Copy link

melfon commented Mar 11, 2025

Description

Fail to open an dll built with .NET 9.0 /clr:netcore.

It works fine with .NET 8.0, but with .NET 9.0 it only works during debugging and if Suppress JIT optimization on module load is enabled. It never works in release.

It is somehow connected to the main application loading the dll. It works if the main app is written in C#.

Reproduction Steps

Created a simple app to reproduce the problem.
DllExport

Run DebugTestApp to see the problem. Debug uses NetApp, which works.

Works fine if using .NET 8, but crashes if using .NET 9.

Expected behavior

As with .NET 8.0

Actual behavior

'TestApp.exe' (Win32): Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\9.0.2\clrjit.dll'. Symbol loading disabled by Include/Exclude setting.
Exception thrown at 0x00007FFB66DF53EB (clrjit.dll) in TestApp.exe: 0xC000008E: Floating-point division by zero (parameters: 0x0000000000000000, 0x0000000000001924).

Regression?

Works with .NET 8

Known Workarounds

Enable Suppress JIT optimization on module load in VS to get it working during debugging within VS. It never works in release.

Configuration

No response

Other information

No response

@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Mar 11, 2025
@EgorBo
Copy link
Member

EgorBo commented Mar 11, 2025

Does not repro for me in .NET 9.0 and Release assuming I repeated the steps correctly

I changed TFM to net9.0 for NetApp.csproj and ran it under Release (with "Enable Suppress JIT optimization on module load i" disabled)

@jkotas jkotas added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI and removed area-Diagnostics-coreclr labels Mar 11, 2025
Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@melfon
Copy link
Author

melfon commented Mar 11, 2025

The problem is with the TestApp. Use DllExport to reproduce the problem, DebugTestApp fails, DebugTestApp.NET8 works. NetApp is only used to show that somehow the problem is dependent on the application calling the dll.

You can also test it by starting TestApp directly from the browser. DllExportTest\bin\Release\TestApp.exe will fail.

@EgorBo
Copy link
Member

EgorBo commented Mar 11, 2025

The problem is with the TestApp. Use DllExport to reproduce the problem, DebugTestApp fails, DebugTestApp.NET8 works. NetApp is only used to show that somehow the problem is dependent on the application calling the dll.

You can also test it by starting TestApp directly from the browser. DllExportTest\bin\Release\TestApp.exe will fail.

@melfon not sure I follow - I cloned you rerpo with C# and C++ project. but then there is also a standalone binary (it's not managed) - is there a source for it?

@AndyAyersMS
Copy link
Member

I can repro, the error is in profile synthesis:

Image

clrjit.dll!ProfileSynthesis::GaussSeidelSolver() Line 1416
	at D:\a\_work\1\s\src\coreclr\jit\fgprofilesynthesis.cpp(1416)
[Inline Frame] clrjit.dll!ProfileSynthesis::ComputeBlockWeights() Line 1113
	at D:\a\_work\1\s\src\coreclr\jit\fgprofilesynthesis.cpp(1113)
clrjit.dll!ProfileSynthesis::Run(ProfileSynthesisOption option) Line 100
	at D:\a\_work\1\s\src\coreclr\jit\fgprofilesynthesis.cpp(100)
[Inline Frame] clrjit.dll!ProfileSynthesis::Run(Compiler *) Line 37
	at D:\a\_work\1\s\src\coreclr\jit\fgprofilesynthesis.h(37)
clrjit.dll!Compiler::fgIncorporateProfileData() Line 2919
	at D:\a\_work\1\s\src\coreclr\jit\fgprofile.cpp(2919)
[Inline Frame] clrjit.dll!Phase::Run() Line 61
	at D:\a\_work\1\s\src\coreclr\jit\phase.cpp(61)
[Inline Frame] clrjit.dll!DoPhase(Compiler *) Line 143
	at D:\a\_work\1\s\src\coreclr\jit\phase.h(143)
clrjit.dll!Compiler::compCompile(void * * methodCodePtr, unsigned int * methodCodeSize, JitFlags * compileFlags) Line 4642

Here change is 100 and oldWeight is 0.

@melfon I wonder if something in the host changes the FP exception modes. Normally this computation would not raise an exception and just compute infinity.

@melfon
Copy link
Author

melfon commented Mar 11, 2025

The problem is with the TestApp. Use DllExport to reproduce the problem, DebugTestApp fails, DebugTestApp.NET8 works. NetApp is only used to show that somehow the problem is dependent on the application calling the dll.
You can also test it by starting TestApp directly from the browser. DllExportTest\bin\Release\TestApp.exe will fail.

@melfon not sure I follow - I cloned you rerpo with C# and C++ project. but then there is also a standalone binary (it's not managed) - is there a source for it?

@EgorBo The problem is that sometimes I have external apps, in this case the TestApp that will load a dll.
DllExport creates a very simple dll that TestApp will load and call the exported method Load() in dllmain.cpp. Normally the load method will call some C# class, but the problem can be reproduced even without that. I had no problem doing this before with NET8, but it fails with NET9.

Use configuration DebugTestApp with DllExport project and you should be able to reproduce the error.

@melfon
Copy link
Author

melfon commented Mar 11, 2025

I can repro, the error is in profile synthesis:

Image

clrjit.dll!ProfileSynthesis::GaussSeidelSolver() Line 1416
	at D:\a\_work\1\s\src\coreclr\jit\fgprofilesynthesis.cpp(1416)
[Inline Frame] clrjit.dll!ProfileSynthesis::ComputeBlockWeights() Line 1113
	at D:\a\_work\1\s\src\coreclr\jit\fgprofilesynthesis.cpp(1113)
clrjit.dll!ProfileSynthesis::Run(ProfileSynthesisOption option) Line 100
	at D:\a\_work\1\s\src\coreclr\jit\fgprofilesynthesis.cpp(100)
[Inline Frame] clrjit.dll!ProfileSynthesis::Run(Compiler *) Line 37
	at D:\a\_work\1\s\src\coreclr\jit\fgprofilesynthesis.h(37)
clrjit.dll!Compiler::fgIncorporateProfileData() Line 2919
	at D:\a\_work\1\s\src\coreclr\jit\fgprofile.cpp(2919)
[Inline Frame] clrjit.dll!Phase::Run() Line 61
	at D:\a\_work\1\s\src\coreclr\jit\phase.cpp(61)
[Inline Frame] clrjit.dll!DoPhase(Compiler *) Line 143
	at D:\a\_work\1\s\src\coreclr\jit\phase.h(143)
clrjit.dll!Compiler::compCompile(void * * methodCodePtr, unsigned int * methodCodeSize, JitFlags * compileFlags) Line 4642

Here change is 100 and oldWeight is 0.

@melfon I wonder if something in the host changes the FP exception modes. Normally this computation would not raise an exception and just compute infinity.

That at least explains the division by zero.

@AndyAyersMS
Copy link
Member

See for example the discussion in #109997 -- if you want to modify FP exceptional behavior you have to be careful to restore it before invoking any .NET code.

@melfon
Copy link
Author

melfon commented Mar 11, 2025

Ok, now I understand. So there is a difference in behavior between NET8 and NET9. To get this working in NET9, the main application has to disable zero division checks. I recompiled TestApp.exe and got it working. This could cause a problem for older apps that can not be recompiled.

@AndyAyersMS
Copy link
Member

AFAIK this FP mode sensitivity is not a new requirement in .NET 9. But in .NET 9 it may now be exposed in more places.

@AndyAyersMS
Copy link
Member

Though it looks like as good citizens we should probably avoid depending on divide by zero in that one spot in the JIT. I will put up a PR, though not sure if it will qualify for backporting to .NET 9.

AndyAyersMS added a commit to AndyAyersMS/runtime that referenced this issue Mar 11, 2025
This can trip up users that have enabled floating point exceptions.

While we don't generally support changing the exception modes we also
can easily avoid dividing by zero here.

Addresses dotnet#113369
AndyAyersMS added a commit that referenced this issue Mar 12, 2025
This can trip up users that have enabled floating point exceptions.

While we don't generally support changing the exception modes we also
can easily avoid dividing by zero here.

Addresses #113369
@melfon
Copy link
Author

melfon commented Mar 12, 2025

Though it looks like as good citizens we should probably avoid depending on divide by zero in that one spot in the JIT. I will put up a PR, though not sure if it will qualify for backporting to .NET 9.

@AndyAyersMS Thanks for the support and quick response!

github-actions bot pushed a commit that referenced this issue Mar 12, 2025
This can trip up users that have enabled floating point exceptions.

While we don't generally support changing the exception modes we also
can easily avoid dividing by zero here.

Addresses #113369
@AndyAyersMS
Copy link
Member

FYI I have put this up for consideration as a .NET 9 fix: #113418 -- will update this once a decision is made.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI untriaged New issue has not been triaged by the area owner
Projects
None yet
Development

No branches or pull requests

4 participants