Skip to content

Commit

Permalink
Add exception interop test for validating native exception interop on…
Browse files Browse the repository at this point in the history
… Windows + CoreCLR. (#70110)
  • Loading branch information
jkoritzinsky authored Jun 22, 2022
1 parent 4388cc5 commit f20a046
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

include_directories(${INC_PLATFORM_DIR})
add_library(ExceptionInteropNative SHARED ExceptionInteropNative.cpp)
target_link_libraries(ExceptionInteropNative PRIVATE platformdefines)
125 changes: 125 additions & 0 deletions src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Xunit;
using static ExceptionInteropNative;

internal unsafe static class ExceptionInteropNative
{
[DllImport(nameof(ExceptionInteropNative))]
public static extern void ThrowException();

[DllImport(nameof(ExceptionInteropNative))]
public static extern void NativeFunction();

[DllImport(nameof(ExceptionInteropNative))]
public static extern void CallCallback(delegate* unmanaged<void> cb);
}

public unsafe static class ExceptionInterop
{
[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
[SkipOnMono("Exception interop not supported on Mono.")]
public static void ThrowNativeExceptionAndCatchInFrame()
{
bool caughtException = false;
try
{
ThrowException();
}
catch
{
caughtException = true;
// Try calling another P/Invoke in the catch block to make sure we have everything set up
// to recover from the exceptional control flow.
NativeFunction();
}
Assert.True(caughtException);
}

[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
[SkipOnMono("Exception interop not supported on Mono.")]
public static void ThrowManagedExceptionThroughNativeAndCatchInFrame()
{
bool caughtException = false;
try
{
CallCallback(&ThrowManagedException);
}
catch
{
caughtException = true;
// Try calling another P/Invoke in the catch block to make sure we have everything set up
// to recover from the exceptional control flow.
NativeFunction();
}
Assert.True(caughtException);

[UnmanagedCallersOnly]
static void ThrowManagedException()
{
throw new Exception();
}
}

[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
[SkipOnMono("Exception interop not supported on Mono.")]
public static void ThrowNativeExceptionAndCatchInFrameWithFilter()
{
bool caughtException = false;
try
{
ThrowException();
}
catch (Exception) when (Filter())
{
caughtException = true;
// Try calling another P/Invoke in the catch block to make sure we have everything set up
// to recover from the exceptional control flow.
NativeFunction();
}
Assert.True(caughtException);

// Aggresively inline to make sure the call to NativeFunction is in the filter clause
[MethodImpl(MethodImplOptions.AggressiveInlining)]
bool Filter()
{
NativeFunction();
return true;
}
}

[Fact]
[PlatformSpecific(TestPlatforms.Windows)]
[SkipOnMono("Exception interop not supported on Mono.")]
public static void ThrowNativeExceptionAndCatchInFrameWithFinally()
{
bool caughtException = false;
try
{
try
{
ThrowException();
}
finally
{
// Try calling another P/Invoke in the finally block before the catch
// to make sure we have everything set up
// to recover from the exceptional control flow.
NativeFunction();
}
}
catch
{
caughtException = true;
}

Assert.True(caughtException);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<CMakeProjectReference Include="CMakeLists.txt" />
<Compile Include="ExceptionInterop.cs" />
</ItemGroup>
</Project>

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#include <exception>
#include <platformdefines.h>

extern "C" DLL_EXPORT void STDMETHODCALLTYPE ThrowException()
{
throw std::exception{};
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE NativeFunction()
{
}

extern "C" DLL_EXPORT void STDMETHODCALLTYPE CallCallback(void (*cb)())
{
cb();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<CMakeProjectReference Include="CMakeLists.txt" />
<Compile Include="ExceptionInterop.cs" />
</ItemGroup>
</Project>

0 comments on commit f20a046

Please sign in to comment.