-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
384 additions
and
0 deletions.
There are no files selected for viewing
20 changes: 20 additions & 0 deletions
20
.../baseservices/exceptions/unhandledHandler/ForeignThreadRevPInvokeUnhandled/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
project (ForeignThreadRevPInvokeUnhandledNative) | ||
|
||
include_directories(${INC_PLATFORM_DIR}) | ||
|
||
if(CLR_CMAKE_HOST_OSX) | ||
# Enable non-POSIX pthreads APIs, which by default are not included in the pthreads header | ||
add_definitions(-D_DARWIN_C_SOURCE) | ||
endif(CLR_CMAKE_HOST_OSX) | ||
|
||
set(SOURCES ForeignThreadRevPInvokeUnhandledNative.cpp) | ||
|
||
if(NOT CLR_CMAKE_HOST_WIN32) | ||
add_compile_options(-pthread) | ||
endif() | ||
|
||
# add the executable | ||
add_library (ForeignThreadRevPInvokeUnhandledNative SHARED ${SOURCES}) | ||
|
||
# add the install targets | ||
install (TARGETS ForeignThreadRevPInvokeUnhandledNative DESTINATION bin) |
94 changes: 94 additions & 0 deletions
94
...ons/unhandledHandler/ForeignThreadRevPInvokeUnhandled/ForeignThreadRevPInvokeUnhandled.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// 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.Threading; | ||
using System.Threading.Tasks; | ||
using System.Runtime.InteropServices; | ||
using Xunit; | ||
|
||
public delegate void MyCallback(); | ||
|
||
public class PInvokeRevPInvokeUnhandled | ||
{ | ||
[DllImport("ForeignThreadRevPInvokeUnhandled")] | ||
public static extern void InvokeCallback(MyCallback callback); | ||
|
||
[DllImport("ForeignThreadRevPInvokeUnhandled")] | ||
public static extern void InvokeCallbackOnNewThread(MyCallback callback); | ||
|
||
[ThreadStatic] | ||
private static Exception lastEx; | ||
private static bool expectUnhandledException = false; | ||
|
||
private static bool Handler(Exception ex) | ||
{ | ||
lastEx = ex; | ||
return true; | ||
} | ||
|
||
private static void SetHandler() | ||
{ | ||
System.Runtime.ExceptionServices.ExceptionHandling.SetUnhandledExceptionHandler(Handler); | ||
} | ||
|
||
// test-wide setup | ||
static PInvokeRevPInvokeUnhandled() | ||
{ | ||
AppDomain.CurrentDomain.UnhandledException += (_, _) => | ||
{ | ||
if (expectUnhandledException && | ||
lastEx == null) | ||
{ | ||
Environment.Exit(100); | ||
} | ||
}; | ||
|
||
SetHandler(); | ||
} | ||
|
||
public static void RunTest() | ||
{ | ||
// sanity check, the handler should be working in a separate thread | ||
Thread th = new Thread(() => | ||
{ | ||
try | ||
{ | ||
lastEx = null; | ||
throw new Exception("here is an unhandled exception1"); | ||
Assert.Fail(); | ||
} | ||
finally | ||
{ | ||
Assert.Equal("here is an unhandled exception1", lastEx.Message); | ||
} | ||
}); | ||
|
||
th.Start(); | ||
th.Join(); | ||
|
||
expectUnhandledException = true; | ||
InvokeCallbackOnNewThread(() => { | ||
try | ||
{ | ||
lastEx = null; | ||
throw new Exception("here is an unhandled exception2"); | ||
Assert.Fail(); | ||
} | ||
finally | ||
{ | ||
Assert.Null(lastEx); | ||
} | ||
}); | ||
|
||
Assert.Fail(); | ||
} | ||
|
||
public static int Main() | ||
{ | ||
RunTest(); | ||
|
||
// should not reach here | ||
return 42; | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
...unhandledHandler/ForeignThreadRevPInvokeUnhandled/ForeignThreadRevPInvokeUnhandled.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<!-- Needed for CMakeProjectReference --> | ||
<RequiresProcessIsolation>true</RequiresProcessIsolation> | ||
<!-- Test requires EH-clean Main --> | ||
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator> | ||
<MonoAotIncompatible>true</MonoAotIncompatible> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Compile Include="ForeignThreadRevPInvokeUnhandled.cs" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<CMakeProjectReference Include="CMakeLists.txt" /> | ||
</ItemGroup> | ||
</Project> |
63 changes: 63 additions & 0 deletions
63
...andledHandler/ForeignThreadRevPInvokeUnhandled/ForeignThreadRevPInvokeUnhandledNative.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
#include "stdio.h" | ||
#include <stdlib.h> | ||
|
||
#ifdef _WIN32 | ||
#pragma warning(push) | ||
#pragma warning(disable:4265 4577) | ||
#include <thread> | ||
#pragma warning(pop) | ||
#else // _WIN32 | ||
#include <pthread.h> | ||
#endif // _WIN32 | ||
|
||
// Work around typedef redefinition: platformdefines.h defines error_t | ||
// as unsigned while it's defined as int in errno.h. | ||
#define error_t error_t_ignore | ||
#include <platformdefines.h> | ||
#undef error_t | ||
|
||
typedef void (*PFNACTION1)(); | ||
extern "C" DLL_EXPORT void InvokeCallback(PFNACTION1 callback) | ||
{ | ||
callback(); | ||
} | ||
|
||
#ifndef _WIN32 | ||
void* InvokeCallbackUnix(void* callback) | ||
{ | ||
InvokeCallback((PFNACTION1)callback); | ||
return NULL; | ||
} | ||
|
||
#define AbortIfFail(st) if (st != 0) abort() | ||
|
||
#endif // !_WIN32 | ||
|
||
extern "C" DLL_EXPORT void InvokeCallbackOnNewThread(PFNACTION1 callback) | ||
{ | ||
#ifdef _WIN32 | ||
std::thread t1(InvokeCallback, callback); | ||
t1.join(); | ||
#else // _WIN32 | ||
// For Unix, we need to use pthreads to create the thread so that we can set its stack size. | ||
// We need to set the stack size due to the very small (80kB) default stack size on MUSL | ||
// based Linux distros. | ||
pthread_attr_t attr; | ||
int st = pthread_attr_init(&attr); | ||
AbortIfFail(st); | ||
|
||
// set stack size to 1.5MB | ||
st = pthread_attr_setstacksize(&attr, 0x180000); | ||
AbortIfFail(st); | ||
|
||
pthread_t t; | ||
st = pthread_create(&t, &attr, InvokeCallbackUnix, (void*)callback); | ||
AbortIfFail(st); | ||
|
||
st = pthread_join(t, NULL); | ||
AbortIfFail(st); | ||
#endif // _WIN32 | ||
} |
20 changes: 20 additions & 0 deletions
20
src/tests/baseservices/exceptions/unhandledHandler/PInvokeRevPInvokeUnhandled/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
project (PInvokeRevPInvokeUnhandledNative) | ||
|
||
include_directories(${INC_PLATFORM_DIR}) | ||
|
||
if(CLR_CMAKE_HOST_OSX) | ||
# Enable non-POSIX pthreads APIs, which by default are not included in the pthreads header | ||
add_definitions(-D_DARWIN_C_SOURCE) | ||
endif(CLR_CMAKE_HOST_OSX) | ||
|
||
set(SOURCES PInvokeRevPInvokeUnhandledNative.cpp) | ||
|
||
if(NOT CLR_CMAKE_HOST_WIN32) | ||
add_compile_options(-pthread) | ||
endif() | ||
|
||
# add the executable | ||
add_library (PInvokeRevPInvokeUnhandledNative SHARED ${SOURCES}) | ||
|
||
# add the install targets | ||
install (TARGETS PInvokeRevPInvokeUnhandledNative DESTINATION bin) |
94 changes: 94 additions & 0 deletions
94
...ices/exceptions/unhandledHandler/PInvokeRevPInvokeUnhandled/PInvokeRevPInvokeUnhandled.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
// 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.Threading; | ||
using System.Threading.Tasks; | ||
using System.Runtime.InteropServices; | ||
using Xunit; | ||
|
||
public delegate void MyCallback(); | ||
|
||
public class PInvokeRevPInvokeUnhandled | ||
{ | ||
[DllImport("PInvokeRevPInvokeUnhandledNative")] | ||
public static extern void InvokeCallback(MyCallback callback); | ||
|
||
[DllImport("PInvokeRevPInvokeUnhandledNative")] | ||
public static extern void InvokeCallbackOnNewThread(MyCallback callback); | ||
|
||
[ThreadStatic] | ||
private static Exception lastEx; | ||
private static bool expectUnhandledException = false; | ||
|
||
private static bool Handler(Exception ex) | ||
{ | ||
lastEx = ex; | ||
return true; | ||
} | ||
|
||
private static void SetHandler() | ||
{ | ||
System.Runtime.ExceptionServices.ExceptionHandling.SetUnhandledExceptionHandler(Handler); | ||
} | ||
|
||
// test-wide setup | ||
static PInvokeRevPInvokeUnhandled() | ||
{ | ||
AppDomain.CurrentDomain.UnhandledException += (_, _) => | ||
{ | ||
if (expectUnhandledException && | ||
lastEx == null) | ||
{ | ||
Environment.Exit(100); | ||
} | ||
}; | ||
|
||
SetHandler(); | ||
} | ||
|
||
public static void RunTest() | ||
{ | ||
// sanity check, the handler should be working in a separate thread | ||
Thread th = new Thread(() => | ||
{ | ||
try | ||
{ | ||
lastEx = null; | ||
throw new Exception("here is an unhandled exception1"); | ||
Assert.Fail(); | ||
} | ||
finally | ||
{ | ||
Assert.Equal("here is an unhandled exception1", lastEx.Message); | ||
} | ||
}); | ||
|
||
th.Start(); | ||
th.Join(); | ||
|
||
expectUnhandledException = true; | ||
InvokeCallback(() => { | ||
try | ||
{ | ||
lastEx = null; | ||
throw new Exception("here is an unhandled exception2"); | ||
Assert.Fail(); | ||
} | ||
finally | ||
{ | ||
Assert.Null(lastEx); | ||
} | ||
}); | ||
|
||
Assert.Fail(); | ||
} | ||
|
||
public static int Main() | ||
{ | ||
RunTest(); | ||
|
||
// should not reach here | ||
return 42; | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
.../exceptions/unhandledHandler/PInvokeRevPInvokeUnhandled/PInvokeRevPInvokeUnhandled.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<!-- Needed for CMakeProjectReference --> | ||
<RequiresProcessIsolation>true</RequiresProcessIsolation> | ||
<!-- Test requires EH-clean Main --> | ||
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator> | ||
<MonoAotIncompatible>true</MonoAotIncompatible> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Compile Include="PInvokeRevPInvokeUnhandled.cs" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<CMakeProjectReference Include="CMakeLists.txt" /> | ||
</ItemGroup> | ||
</Project> |
63 changes: 63 additions & 0 deletions
63
...ceptions/unhandledHandler/PInvokeRevPInvokeUnhandled/PInvokeRevPInvokeUnhandledNative.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
#include "stdio.h" | ||
#include <stdlib.h> | ||
|
||
#ifdef _WIN32 | ||
#pragma warning(push) | ||
#pragma warning(disable:4265 4577) | ||
#include <thread> | ||
#pragma warning(pop) | ||
#else // _WIN32 | ||
#include <pthread.h> | ||
#endif // _WIN32 | ||
|
||
// Work around typedef redefinition: platformdefines.h defines error_t | ||
// as unsigned while it's defined as int in errno.h. | ||
#define error_t error_t_ignore | ||
#include <platformdefines.h> | ||
#undef error_t | ||
|
||
typedef void (*PFNACTION1)(); | ||
extern "C" DLL_EXPORT void InvokeCallback(PFNACTION1 callback) | ||
{ | ||
callback(); | ||
} | ||
|
||
#ifndef _WIN32 | ||
void* InvokeCallbackUnix(void* callback) | ||
{ | ||
InvokeCallback((PFNACTION1)callback); | ||
return NULL; | ||
} | ||
|
||
#define AbortIfFail(st) if (st != 0) abort() | ||
|
||
#endif // !_WIN32 | ||
|
||
extern "C" DLL_EXPORT void InvokeCallbackOnNewThread(PFNACTION1 callback) | ||
{ | ||
#ifdef _WIN32 | ||
std::thread t1(InvokeCallback, callback); | ||
t1.join(); | ||
#else // _WIN32 | ||
// For Unix, we need to use pthreads to create the thread so that we can set its stack size. | ||
// We need to set the stack size due to the very small (80kB) default stack size on MUSL | ||
// based Linux distros. | ||
pthread_attr_t attr; | ||
int st = pthread_attr_init(&attr); | ||
AbortIfFail(st); | ||
|
||
// set stack size to 1.5MB | ||
st = pthread_attr_setstacksize(&attr, 0x180000); | ||
AbortIfFail(st); | ||
|
||
pthread_t t; | ||
st = pthread_create(&t, &attr, InvokeCallbackUnix, (void*)callback); | ||
AbortIfFail(st); | ||
|
||
st = pthread_join(t, NULL); | ||
AbortIfFail(st); | ||
#endif // _WIN32 | ||
} |