4

I have basically a duplicate question but for .NET Core.

I have Core console app:

class Program
{
    static void DoSomeAccessViolation()
    {
        // if you have any questions about why this throws,
        // the answer is "42", of course

        var ptr = new IntPtr(42);
        Marshal.StructureToPtr(42, ptr, true);
    }

    [SecurityCritical]
    [HandleProcessCorruptedStateExceptions]
    static void Main(string[] args)
    {
        try
        {
            DoSomeAccessViolation();
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex);
        }
    }
}

I've tried to add a Settings.setting file

<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="ConsoleApp2" GeneratedClassName="Settings1">
  <Profiles />
  <Settings>
    <Setting Name="legacyCorruptedStateExceptionsPolicy" Type="System.Boolean" Scope="Application">
      <Value Profile="(Default)">True</Value>
    </Setting>
  </Settings>
</SettingsFile>

and I've tried to set an environment variable according to docs:

C:\>set COMPlus_legacyCorruptedStateExceptionsPolicy=1
C:\>dotnet run

or

C:\>set COMPlus_legacyCorruptedStateExceptionsPolicy=true
C:\>dotnet run

(on Windows). But nothing works, the app always crashes hard without printing the exception.

HH321
  • 502
  • 1
  • 6
  • 20

3 Answers3

2

Some background I've been digging up on the subject, in chronological order...

dotnet/coreclr Issue #9045: Strip corrupted state exceptions handling

dotnet/coreclr PR #10957: Do not honor attribute HandleProcessCorruptedStateExceptions

dotnet/coreclr Issue #19192: Unable to catch in managed code any user exception thrown from native Linux code

I'm SOL currently. Have to create an unmanaged wrapper of sorts to catch external CSEs.

You can try a few more options, specifically FailFastOnCorruptedStateException combined with legacyCorruptedStateExceptionsPolicy.

TylerY86
  • 3,737
  • 16
  • 29
1

I ran your code and the exception being raised is ExecutionEngineException. This is a fatal error in the runtime, meaning runtime cannot execute your program further. You can't catch this exception for a good reason: you cannot handle it. There is nothing your code could do to "fix" the runtime and continue operating.

From Microsoft docu: The exception that is thrown when there is an internal error in the execution engine of the common language runtime. And: This type previously indicated an unspecified fatal error in the runtime. The runtime no longer raises this exception so this type is obsolete.

Maxim Zabolotskikh
  • 3,091
  • 20
  • 21
  • I'm actually looking into it not for this specific crash - I'm using a native library (that has a failing assertion) in a web server. It happens once a week on so it's hard to debug to see the exact exception. Would be nice to print the exception, see what request caused it and quit instead of FailFast with a single line in syslog – HH321 Feb 09 '18 at 10:09
  • 1
    "fix" or "recover" from a bad crash is not the only use-case. printing out some useful details might succeed, and would accelerate debugging time of such crashes. I was actually doing something like that in .Net Framework, and now looking for doing it in dotnet core. – lev haikin Feb 28 '18 at 07:14
0

The only thing about this remains in .net core is legacyCorruptedStateExceptionsPolicy behavior.

To enable this, you must set COMPlus_legacyCorruptedStateExceptionsPolicy environment variable to 1 before your process start. But, in .net core it will catch far less corrupted state exceptions than in .net, due to decisions made during .net porting :(

For example, if you replace in your code Marshal.StructureToPtr(42, (IntPtr)42, true); with Marshal.ReadInt32((IntPtr)42); (and set the environment variable) AVE will be generated and captured successfully.

You can read details about this problem here.

Overall about corrupted state exceptions in .net core:

  1. To catch some of them set COMPlus_legacyCorruptedStateExceptionsPolicy environment variable to 1 before your process start.
  2. If you get CSE from native calls. Try to move exception handling there (if you have the source), or try unmanaged wrapper as TylerY86 suggested.
  3. Write WatchDog process to check your app crashes, if it's important. Then look to Event Log and analyzing the crash dumps...
Kirsan
  • 254
  • 3
  • 5