Skip to content

Netcore2.2 app aborts in release configuration on a Linux machine #13749

Closed

Description

@rossgurbutt

We have an issue with the attached (heavily cut down) project which targets netcoreapp2.2.
We build and publish the app in both Release and Debug configurations.
When running on Windows, Release and Debug both complete successfully.
When running on Linux, Debug completes successfully, however Release aborts with one of the following errors:

  • System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
  • Segmentation fault

The program is very simple, contains no unmanaged code, no third party dependencies, and almost no logic at all.

Linux machine details (however this happens on all the different Linux machines / OSs available to us):

Operating system: CentOS Linux 7 (Core)
Kernel: Linux 3.10.0-862.11.6.el7.x86_64

dotnet --info:

.NET Core SDK (reflecting any global.json):
 Version:   2.2.402
 Commit:    c7f2f96116

Runtime Environment:
 OS Name:     centos
 OS Version:  7
 OS Platform: Linux
 RID:         centos.7-x64
 Base Path:   /usr/share/dotnet/sdk/2.2.402/

Host (useful for support):
  Version: 2.2.7
  Commit:  b1e29ae826

.NET Core SDKs installed:
  2.2.402 [/usr/share/dotnet/sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.2.7 [/usr/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.2.7 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.2.7 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

Program.zip

category:correctness
theme:calling-convention
skill-level:beginner
cost:small

Activity

  1. janvorli commented on Nov 8, 2019

    @janvorli
    Member

    @rossgurbutt than you for reporting it. I can confirm that I can repro it locally on my Ubuntu 16.04 box with .NET Core 2.2. However, it works fine with .NET Core 3.0.
    Since .NET 2.2 in now in maintenance mode (only security updates may be added until it reaches its end of life), I would suggest to move your app to 3.0.

  2. rossgurbutt commented on Nov 8, 2019

    @rossgurbutt
    Author

    @janvorli Thanks for the quick response.
    With our full solution that we can't share here (for obvious proprietary information reasons) we still get the issue in Net Core 3.0, albeit less frequently and less deterministically. Our hope was that the issue may be the same and that identifying the easier to reproduce cause in Net Core 2.2 may also provide the information necessary to fix Net Core 3.0.
    We're going to look into raising a premium support ticket so that we can share more of what is causing it in 3.0, meanwhile also trying to produce a cut-down app that we would be able to log here.

  3. RobSwDev commented on Nov 8, 2019

    @RobSwDev

    @janvorli Was this a known issue in 2.2? Do you have any information about what fails in 2.2 in case that helps us isolate the issue in 3.0?
    For example, the crash we see is very near where we make a call to a native assembly, and I thought for sure that the native assembly would be the culprit, until Ross managed to repro (on 2.2 only) the issue without any native assembly references.

  4. janvorli commented on Nov 8, 2019

    @janvorli
    Member

    @RobSwDev I debugged the build with 2.2 and seeing what happens was somehow familiar, so I have a feeling that I've debugged the original issue in the past myself. But I wasn't able to find a related PR yet.
    I could see that lowest 32 bits of an address that the code was using as a base address to access memory with an added offset of 8 when it crashed were all zeros. That's the pattern that made it feel familiar.
    I'll try to find the PR that has fixed it.

  5. janvorli commented on Nov 8, 2019

    @janvorli
    Member

    The issue was caused by a JIT bug. When Thing1::DoWork1 calls thing2.DoWork2 and passes the same arguments to it (except for the first one that was the thing2), it incorrectly shuffles the arguments from the incoming argument registers and stack slots to the DoWork2's argument registers and slots. Based on the Unix AMD64 calling convention, the parameters to DoWork1 are passed as follows:

                this in RDI
                IThing2 thing2 in RSI
                double[][] array1 in RDX
                double[] array2 in RCX
                int[] array3 in R8
                int[] array4 in R9
                double[] array5 in stack slot 0
                int integer1 in stack slot 1
                int integer2 in stack slot 2
                int integer3 in stack slot 3
                double double1 in XMM0
    

    When it calls the thing2.DoWork2(array1, double1, array3, array4, array5, integer1, integer2, integer3);, the arguments should passed as follows:

                thing2 in RDI (was in RSI)
                array1 in RSI (was in RDX)
                double1 in XMM0 (was in XMM0)
                int[] array3 in RDX (was in R8)
                array4 in RCX (was in R9)
                array5 in R8 (was in stack slot 0)
                int integer1 in R9 (was in stack slot 1)
                int integer2 in stack slot 0 (was in stack slot 2)
                int integer3 in stack slot 1 (was in stack slot 3)
    

    So as you can see, the JIT needs to do these argument moves:

    RSI->RDI
    RDX->RSI
    R8->RDX
    R9->RCX
    Stack slot 0->R8
    Stack slot 1->R9
    Stack slot 2->stack slot 0
    Stack slot 3->Stack slot 1
    

    But in .NET 2.2, there was a bug in JIT that did the moves in an incorrect order. It moved 32 bit from stack slot 2 to stack slot 0 before moving stack slot 0 to R8. So the R8 (which should contain reference to array5) ended up having broken value and accessing it resulted in the crash in your testing app.

    Unfortunately, I was unable to find the PR that fixed this problem.

  6. transferred this issue fromdotnet/coreclron Jan 31, 2020
  7. added this to the 2.2.x milestone on Jan 31, 2020
  8. jkotas commented on Mar 1, 2020

    @jkotas
    Member

    .NET Core 2.2 is out of support.

  9. ghost locked as resolved and limited conversation to collaborators on Dec 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIos-linuxLinux OS (any supported distro)

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions