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

Mono's behavior around .beforefieldinit #77513

Open
EgorBo opened this issue Oct 26, 2022 · 5 comments
Open

Mono's behavior around .beforefieldinit #77513

EgorBo opened this issue Oct 26, 2022 · 5 comments
Assignees
Milestone

Comments

@EgorBo
Copy link
Member

EgorBo commented Oct 26, 2022

The following program:

using System;
using System.Runtime.CompilerServices;

C.TestMethod(false);
Console.WriteLine("Done");

static class C
{
    [MethodImpl(MethodImplOptions.NoInlining)] // doesn't matter, but JIC
    public static int TestMethod(bool cond)
    {
        if (cond)
        {
            // never invoked in this program
            return ClassB.X;
        }
        // always taken
        return 0;
    }
}

public class ClassB
{
    public static readonly int X = GetX();

    static int GetX()
    {
        Console.WriteLine("GetX call!"); // not expected to be invoked in this program
        return 42;
    }
}

Output on Mono:

GetX call!
Done

Output on CoreCLR:

Done

It's not wrong according to ECMA-335:

: BeforeFieldInit behavior is intended for initialization code with no interesting sideeffects, 
where exact timing does not matter. Also, under BeforeFieldInit semantics, type
initializers are allowed to be executed at or before first access to any static field of that type,
at the discretion of the CLI.

However, it'd be nice to align this behavior with CoreCLR to avoid potential issues like the one I've hit in #77398 (comment). And, obviously, in this case Mono executed completely redundant code (did more work). I think I've hit the same issue in the past where static initialization in Mono triggered DllImport leading to DllNotFoundException while CoreCLR didn't, can't find the issue.

Related issue: #4346 (see #4346 (comment))

@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Oct 26, 2022
@SamMonoRT SamMonoRT added this to the 8.0.0 milestone May 22, 2023
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label May 22, 2023
@SamMonoRT
Copy link
Member

@LeVladIonescu - please investigate this.

@SamMonoRT
Copy link
Member

@lambdageek - PR is up, but still encountering some CI failures. Moving this to 9.0.0

@SamMonoRT SamMonoRT modified the milestones: 8.0.0, 9.0.0 Aug 14, 2023
@lambdageek
Copy link
Member

@SamMonoRT please add postponed issues to the burndown project and set a priority - otherwise these issues just get left behind and we don't act on them for 11 months and then postpone them again.

akoeplinger added a commit to akoeplinger/runtime that referenced this issue Nov 15, 2023
…ono on Windows

Mono runs static field initializers quite eagerly (dotnet#77513) which means we're getting this DllNotFoundException on Windows, even though this code should only run on Linux:

```
System.Runtime.InteropServices.RuntimeInformationTests.DescriptionNameTests.DumpRuntimeInformationToConsole [FAIL]
   System.TypeInitializationException : The type initializer for 'cgroups' threw an exception.
   ---- System.DllNotFoundException : libSystem.Native
   Stack Trace:
      /_/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Mono.cs(22,0): at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
      /_/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs(57,0): at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
      ----- Inner Stack Trace -----
      /_/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/Microsoft.Interop.LibraryImportGenerator/Microsoft.Interop.LibraryImportGenerator/LibraryImports.g.cs(65,0): at Interop.Sys.GetFormatInfoForMountPoint(String name, Byte* formatNameBuffer, Int32 bufferLength, Int64* formatType)
      /_/src/libraries/Common/src/Interop/Linux/cgroups/Interop.cgroups.cs(215,0): at Interop.cgroups.FindCGroupVersion()
      /_/src/libraries/Common/src/Interop/Linux/cgroups/Interop.cgroups.cs(35,0): at Interop.cgroups..cctor()
```

The workaround is to extract the code into a helper method.
akoeplinger added a commit that referenced this issue Nov 15, 2023
…ono on Windows (#94788)

Mono runs static field initializers quite eagerly (#77513) which means we're getting this DllNotFoundException on Windows, even though this code should only run on Linux:

```
System.Runtime.InteropServices.RuntimeInformationTests.DescriptionNameTests.DumpRuntimeInformationToConsole [FAIL]
   System.TypeInitializationException : The type initializer for 'cgroups' threw an exception.
   ---- System.DllNotFoundException : libSystem.Native
   Stack Trace:
      /_/src/mono/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.Mono.cs(22,0): at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
      /_/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs(57,0): at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)
      ----- Inner Stack Trace -----
      /_/src/libraries/System.Runtime/tests/System.Runtime.InteropServices.RuntimeInformation.Tests/Microsoft.Interop.LibraryImportGenerator/Microsoft.Interop.LibraryImportGenerator/LibraryImports.g.cs(65,0): at Interop.Sys.GetFormatInfoForMountPoint(String name, Byte* formatNameBuffer, Int32 bufferLength, Int64* formatType)
      /_/src/libraries/Common/src/Interop/Linux/cgroups/Interop.cgroups.cs(215,0): at Interop.cgroups.FindCGroupVersion()
      /_/src/libraries/Common/src/Interop/Linux/cgroups/Interop.cgroups.cs(35,0): at Interop.cgroups..cctor()
```

The workaround is to extract the code into a helper method.
@lambdageek lambdageek modified the milestones: 9.0.0, 10.0.0 Jul 22, 2024
@lambdageek
Copy link
Member

We should revive #86787 early in .NET 10. static cctor order changes are hard to diagnose and this late in the net9 release it feels risky

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants