Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/coreclr/nativeaot/Runtime/inc/CommonTypes.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,6 @@
#ifndef __COMMON_TYPES_H__
#define __COMMON_TYPES_H__

#include <assert.h>
#include <cstddef>
#include <cstdint>
#include <stdlib.h>
Expand Down
104 changes: 4 additions & 100 deletions src/coreclr/nativeaot/Runtime/thread.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,6 @@
#include "CommonTypes.h"
#include "CommonMacros.h"
#include "daccess.h"
#include "CommonMacros.inl"
#include "PalRedhawkCommon.h"
#include "PalRedhawk.h"
#include "rhassert.h"
Expand All@@ -28,11 +27,6 @@
#include "RhConfig.h"
#include "RhVolatile.h"

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
#include <signal.h>
#include <sys/mman.h>
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

#ifndef DACCESS_COMPILE

EXTERN_C NATIVEAOT_API void* REDHAWK_CALLCONV RhpHandleAlloc(void* pObject, int type);
Expand DownExpand Up@@ -287,9 +281,6 @@ void Thread::Construct()
if (StressLog::StressLogOn(~0u, 0))
m_pThreadStressLog = StressLog::CreateThreadStressLog(this);
#endif // STRESS_LOG
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
EnsureSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

// Everything else should be initialized to 0 via the static initialization of tls_CurrentThread.

Expand All@@ -306,89 +297,6 @@ void Thread::Construct()
ASSERT(m_interruptedContext == NULL);
}

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void Thread::FreeSignalAlternateStack()
{
void *altstack = m_alternateStack;
m_alternateStack = nullptr;

if (altstack != nullptr)
{
stack_t ss, oss;
// The man page for sigaltstack says that when the ss.ss_flags is set to SS_DISABLE,
// all other ss fields are ignored. However, MUSL implementation checks that the
// ss_size is >= MINSIGSTKSZ even in this case.
ss.ss_size = MINSIGSTKSZ;
ss.ss_flags = SS_DISABLE;
ss.ss_sp = NULL;
int st = sigaltstack(&ss, &oss);
if ((st == 0) && (oss.ss_flags != SS_DISABLE))
{
// Make sure this altstack is this PAL's before freeing.
if (oss.ss_sp == altstack)
{
int st = munmap(oss.ss_sp, oss.ss_size);
_ASSERTE(st == 0);
}
}
}
}

bool Thread::EnsureSignalAlternateStack()
{
int st = 0;

stack_t oss;

// Query the current alternate signal stack
st = sigaltstack(NULL, &oss);
if ((st == 0) && (oss.ss_flags == SS_DISABLE))
{
// There is no alternate stack for SIGSEGV handling installed yet so allocate one

// We include the size of the SignalHandlerWorkerReturnPoint in the alternate stack size since the
// context contained in it is large and the SIGSTKSZ was not sufficient on ARM64 during testing.
int altStackSize = SIGSTKSZ;
#ifdef HAS_ADDRESS_SANITIZER
// Asan also uses alternate stack so we increase its size on the SIGSTKSZ * 4 that enough for asan
// (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc)
altStackSize += SIGSTKSZ * 4;
#endif
altStackSize = ALIGN_UP(altStackSize, PalOsPageSize());
int flags = MAP_ANONYMOUS | MAP_PRIVATE;
#ifdef MAP_STACK
flags |= MAP_STACK;
#endif
void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, flags, -1, 0);
if (altStack != MAP_FAILED)
{
// create a guard page for the alternate stack
st = mprotect(altStack, PalOsPageSize(), PROT_NONE);
if (st == 0)
{
stack_t ss;
ss.ss_sp = (char*)altStack;
ss.ss_size = altStackSize;
ss.ss_flags = 0;
st = sigaltstack(&ss, NULL);
}

if (st == 0)
{
m_alternateStack = altStack;
}
else
{
int st2 = munmap(altStack, altStackSize);
_ASSERTE(st2 == 0);
}
}
}

return (st == 0);
}
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

bool Thread::IsInitialized()
{
return (m_ThreadStateFlags != TSF_Unknown);
Expand DownExpand Up@@ -453,10 +361,6 @@ void Thread::Destroy()
}
#endif //FEATURE_SUSPEND_REDIRECTION

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

ASSERT(m_pGCFrameRegistrations == NULL);
}

Expand DownExpand Up@@ -962,19 +866,19 @@ void Thread::Unhijack()
}

// This unhijack routine is called to undo a hijack, that is potentially on a different thread.
//
//
// Although there are many code sequences (here and in asm) to
// perform an unhijack operation, they will never execute concurrently:
//
//
// - A thread may unhijack itself at any time so long as it does that from unmanaged code while in coop mode.
// This ensures that coop thread can access its stack synchronously.
// Unhijacking from unmanaged code ensures that another thread will not attempt to hijack it,
// since we only hijack threads that are executing managed code.
//
//
// - A GC thread may access a thread asynchronously, including unhijacking it.
// Asynchronously accessed thread must be in preemptive mode and should not
// access the managed portion of its stack.
//
//
// - A thread that owns the suspension can access another thread as long as the other thread is
// in preemptive mode or suspended in managed code.
// Either way the other thread cannot be accessing its hijack.
Expand Down
12 changes: 2 additions & 10 deletions src/coreclr/nativeaot/Runtime/thread.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ struct ThreadBuffer
HANDLE m_hPalThread; // WARNING: this may legitimately be INVALID_HANDLE_VALUE
void ** m_ppvHijackedReturnAddressLocation;
void * m_pvHijackedReturnAddress;
uintptr_t m_uHijackedReturnValueFlags;
uintptr_t m_uHijackedReturnValueFlags;
PTR_ExInfo m_pExInfoStackHead;
Object* m_threadAbortException; // ThreadAbortException instance -set only during thread abort
Object* m_pThreadLocalStatics;
Expand All@@ -112,9 +112,6 @@ struct ThreadBuffer
#ifdef FEATURE_GC_STRESS
uint32_t m_uRand; // current per-thread random number
#endif // FEATURE_GC_STRESS
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void * m_alternateStack; // ptr to alternate signal stack
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

struct ReversePInvokeFrame
Expand DownExpand Up@@ -155,7 +152,7 @@ class Thread : private ThreadBuffer
// For suspension APCs it is mostly harmless, but wasteful and in extreme
// cases may force the target thread into stack oveflow.
// We use this flag to avoid sending another APC when one is still going through.
//
//
// On Unix this is an optimization to not queue up more signals when one is
// still being processed.
};
Expand DownExpand Up@@ -315,11 +312,6 @@ class Thread : private ThreadBuffer

bool IsActivationPending();
void SetActivationPending(bool isPending);

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
bool EnsureSignalAlternateStack();
void FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

#ifndef __GCENV_BASE_INCLUDED__
Expand Down
43 changes: 14 additions & 29 deletions src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,9 +11,6 @@
#include "HardwareExceptions.h"
#include "UnixSignals.h"
#include "PalCreateDump.h"
#include "thread.h"
#include "threadstore.h"
#include <sys/mman.h>

#if defined(HOST_APPLE)
#include <mach/mach.h>
Expand DownExpand Up@@ -548,17 +545,6 @@ bool HardwareExceptionHandler(int code, siginfo_t *siginfo, void *context, void*
// Handler for the SIGSEGV signal
void SIGSEGVHandler(int code, siginfo_t *siginfo, void *context)
{
// First check if we have a stack overflow
size_t sp = ((UNIX_CONTEXT *)context)->GetSp();
size_t failureAddress = (size_t)siginfo->si_addr;

// If the failure address is at most one page above or below the stack pointer,
// we have a stack overflow.
if ((failureAddress - (sp - PalOsPageSize())) < (size_t)PalOsPageSize() * 2)
{
PalPrintFatalError("\nProcess is terminating due to StackOverflowException.\n");
RhFailFast();
}
bool isHandled = HardwareExceptionHandler(code, siginfo, context, siginfo->si_addr);
if (isHandled)
{
Expand DownExpand Up@@ -603,8 +589,7 @@ void SIGFPEHandler(int code, siginfo_t *siginfo, void *context)
// Initialize hardware exception handling
bool InitializeHardwareExceptionHandling()
{
// Run SIGSEGV handler on separate stack so we can handle stack overflow. Otherwise, the current (invalid) stack is used and another segfault is raised.
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV, SA_ONSTACK))
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV))
{
return false;
}
Expand All@@ -616,23 +601,23 @@ bool InitializeHardwareExceptionHandling()

#if defined(HOST_APPLE)
#ifndef HOST_TVOS // task_set_exception_ports is not supported on tvOS
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// checks in NativeAOT; continuing execution after LLDB traps an
// EXC_BAD_ACCESS will result in LLDB's EXC_BAD_ACCESS handler being
// invoked again. This also interferes with the translation of SIGFPEs
// to .NET-level ArithmeticExceptions. Work around this here by
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
ASSERT(kr == KERN_SUCCESS);
#endif
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/nativeaot/Runtime/unix/UnixSignals.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,11 +9,11 @@
#include "UnixSignals.h"

// Add handler for hardware exception signal
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags)
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction)
{
struct sigaction newAction;

newAction.sa_flags = SA_RESTART | additionalFlags;
newAction.sa_flags = SA_RESTART;
newAction.sa_handler = NULL;
newAction.sa_sigaction = handler;
newAction.sa_flags |= SA_SIGINFO;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/unix/UnixSignals.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,7 +14,7 @@

typedef void (*SignalHandler)(int code, siginfo_t* siginfo, void* context);

bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags = 0);
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction);
void RestoreSignalHandler(int signal_id, struct sigaction* previousAction);

#endif // __UNIX_SIGNALS_H__
2 changes: 1 addition & 1 deletion src/tests/Common/CoreCLRTestLibrary/Utilities.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ public static bool IsWindowsIoTCore

public static bool IsMonoRuntime => Type.GetType("Mono.RuntimeStructs") != null;
public static bool IsNotMonoRuntime => !IsMonoRuntime;
public static bool IsNativeAot => IsSingleFile && IsNotMonoRuntime && !IsReflectionEmitSupported;
public static bool IsNativeAot => IsNotMonoRuntime && !IsReflectionEmitSupported;

public static bool HasAssemblyFiles => !string.IsNullOrEmpty(typeof(Utilities).Assembly.Location);
public static bool IsSingleFile => !HasAssemblyFiles;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,8 +65,7 @@ struct LargeStruct65536
LargeStruct4096 se;
LargeStruct4096 sf;
}

internal class StackOverflow
class Program
{
[MethodImpl(MethodImplOptions.NoInlining)]
static void InfiniteRecursionA()
Expand DownExpand Up@@ -135,7 +134,7 @@ static void SecondaryThreadsTest(bool smallframe)
}
}

internal static void Run(string[] args)
static void Main(string[] args)
{
bool smallframe = (args[0] == "smallframe");
if (args[1] == "secondary")
Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>
<CLRTestKind>BuildOnly</CLRTestKind>

<Optimize>false</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow.cs" />
</ItemGroup>
</Project>

Original file line numberDiff line numberDiff line change
Expand Up@@ -2,16 +2,16 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;

namespace TestStackOverflow
namespace TestStackOverflow3
{
internal class StackOverflow3
class Program
{
private const int MAX_RECURSIVE_CALLS = 1000000;
static int ctr = 0;

public static void Run()
public static void Main()
{
StackOverflow3 ex = new StackOverflow3();
Program ex = new Program();
ex.Execute();
}

Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>

<Optimize>false</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLRTestKind>BuildOnly</CLRTestKind>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow3.cs" />
</ItemGroup>
</Project>

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/coreclr/nativeaot/Runtime/inc/CommonTypes.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,6 @@
#ifndef __COMMON_TYPES_H__
#define __COMMON_TYPES_H__

#include <assert.h>
#include <cstddef>
#include <cstdint>
#include <stdlib.h>
Expand Down
104 changes: 4 additions & 100 deletions src/coreclr/nativeaot/Runtime/thread.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,6 @@
#include "CommonTypes.h"
#include "CommonMacros.h"
#include "daccess.h"
#include "CommonMacros.inl"
#include "PalRedhawkCommon.h"
#include "PalRedhawk.h"
#include "rhassert.h"
Expand All@@ -28,11 +27,6 @@
#include "RhConfig.h"
#include "RhVolatile.h"

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
#include <signal.h>
#include <sys/mman.h>
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

#ifndef DACCESS_COMPILE

EXTERN_C NATIVEAOT_API void* REDHAWK_CALLCONV RhpHandleAlloc(void* pObject, int type);
Expand DownExpand Up@@ -287,9 +281,6 @@ void Thread::Construct()
if (StressLog::StressLogOn(~0u, 0))
m_pThreadStressLog = StressLog::CreateThreadStressLog(this);
#endif // STRESS_LOG
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
EnsureSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

// Everything else should be initialized to 0 via the static initialization of tls_CurrentThread.

Expand All@@ -306,89 +297,6 @@ void Thread::Construct()
ASSERT(m_interruptedContext == NULL);
}

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void Thread::FreeSignalAlternateStack()
{
void *altstack = m_alternateStack;
m_alternateStack = nullptr;

if (altstack != nullptr)
{
stack_t ss, oss;
// The man page for sigaltstack says that when the ss.ss_flags is set to SS_DISABLE,
// all other ss fields are ignored. However, MUSL implementation checks that the
// ss_size is >= MINSIGSTKSZ even in this case.
ss.ss_size = MINSIGSTKSZ;
ss.ss_flags = SS_DISABLE;
ss.ss_sp = NULL;
int st = sigaltstack(&ss, &oss);
if ((st == 0) && (oss.ss_flags != SS_DISABLE))
{
// Make sure this altstack is this PAL's before freeing.
if (oss.ss_sp == altstack)
{
int st = munmap(oss.ss_sp, oss.ss_size);
_ASSERTE(st == 0);
}
}
}
}

bool Thread::EnsureSignalAlternateStack()
{
int st = 0;

stack_t oss;

// Query the current alternate signal stack
st = sigaltstack(NULL, &oss);
if ((st == 0) && (oss.ss_flags == SS_DISABLE))
{
// There is no alternate stack for SIGSEGV handling installed yet so allocate one

// We include the size of the SignalHandlerWorkerReturnPoint in the alternate stack size since the
// context contained in it is large and the SIGSTKSZ was not sufficient on ARM64 during testing.
int altStackSize = SIGSTKSZ;
#ifdef HAS_ADDRESS_SANITIZER
// Asan also uses alternate stack so we increase its size on the SIGSTKSZ * 4 that enough for asan
// (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc)
altStackSize += SIGSTKSZ * 4;
#endif
altStackSize = ALIGN_UP(altStackSize, PalOsPageSize());
int flags = MAP_ANONYMOUS | MAP_PRIVATE;
#ifdef MAP_STACK
flags |= MAP_STACK;
#endif
void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, flags, -1, 0);
if (altStack != MAP_FAILED)
{
// create a guard page for the alternate stack
st = mprotect(altStack, PalOsPageSize(), PROT_NONE);
if (st == 0)
{
stack_t ss;
ss.ss_sp = (char*)altStack;
ss.ss_size = altStackSize;
ss.ss_flags = 0;
st = sigaltstack(&ss, NULL);
}

if (st == 0)
{
m_alternateStack = altStack;
}
else
{
int st2 = munmap(altStack, altStackSize);
_ASSERTE(st2 == 0);
}
}
}

return (st == 0);
}
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

bool Thread::IsInitialized()
{
return (m_ThreadStateFlags != TSF_Unknown);
Expand DownExpand Up@@ -453,10 +361,6 @@ void Thread::Destroy()
}
#endif //FEATURE_SUSPEND_REDIRECTION

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

ASSERT(m_pGCFrameRegistrations == NULL);
}

Expand DownExpand Up@@ -962,19 +866,19 @@ void Thread::Unhijack()
}

// This unhijack routine is called to undo a hijack, that is potentially on a different thread.
//
//
// Although there are many code sequences (here and in asm) to
// perform an unhijack operation, they will never execute concurrently:
//
//
// - A thread may unhijack itself at any time so long as it does that from unmanaged code while in coop mode.
// This ensures that coop thread can access its stack synchronously.
// Unhijacking from unmanaged code ensures that another thread will not attempt to hijack it,
// since we only hijack threads that are executing managed code.
//
//
// - A GC thread may access a thread asynchronously, including unhijacking it.
// Asynchronously accessed thread must be in preemptive mode and should not
// access the managed portion of its stack.
//
//
// - A thread that owns the suspension can access another thread as long as the other thread is
// in preemptive mode or suspended in managed code.
// Either way the other thread cannot be accessing its hijack.
Expand Down
12 changes: 2 additions & 10 deletions src/coreclr/nativeaot/Runtime/thread.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ struct ThreadBuffer
HANDLE m_hPalThread; // WARNING: this may legitimately be INVALID_HANDLE_VALUE
void ** m_ppvHijackedReturnAddressLocation;
void * m_pvHijackedReturnAddress;
uintptr_t m_uHijackedReturnValueFlags;
uintptr_t m_uHijackedReturnValueFlags;
PTR_ExInfo m_pExInfoStackHead;
Object* m_threadAbortException; // ThreadAbortException instance -set only during thread abort
Object* m_pThreadLocalStatics;
Expand All@@ -112,9 +112,6 @@ struct ThreadBuffer
#ifdef FEATURE_GC_STRESS
uint32_t m_uRand; // current per-thread random number
#endif // FEATURE_GC_STRESS
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void * m_alternateStack; // ptr to alternate signal stack
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

struct ReversePInvokeFrame
Expand DownExpand Up@@ -155,7 +152,7 @@ class Thread : private ThreadBuffer
// For suspension APCs it is mostly harmless, but wasteful and in extreme
// cases may force the target thread into stack oveflow.
// We use this flag to avoid sending another APC when one is still going through.
//
//
// On Unix this is an optimization to not queue up more signals when one is
// still being processed.
};
Expand DownExpand Up@@ -315,11 +312,6 @@ class Thread : private ThreadBuffer

bool IsActivationPending();
void SetActivationPending(bool isPending);

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
bool EnsureSignalAlternateStack();
void FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

#ifndef __GCENV_BASE_INCLUDED__
Expand Down
43 changes: 14 additions & 29 deletions src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,9 +11,6 @@
#include "HardwareExceptions.h"
#include "UnixSignals.h"
#include "PalCreateDump.h"
#include "thread.h"
#include "threadstore.h"
#include <sys/mman.h>

#if defined(HOST_APPLE)
#include <mach/mach.h>
Expand DownExpand Up@@ -548,17 +545,6 @@ bool HardwareExceptionHandler(int code, siginfo_t *siginfo, void *context, void*
// Handler for the SIGSEGV signal
void SIGSEGVHandler(int code, siginfo_t *siginfo, void *context)
{
// First check if we have a stack overflow
size_t sp = ((UNIX_CONTEXT *)context)->GetSp();
size_t failureAddress = (size_t)siginfo->si_addr;

// If the failure address is at most one page above or below the stack pointer,
// we have a stack overflow.
if ((failureAddress - (sp - PalOsPageSize())) < (size_t)PalOsPageSize() * 2)
{
PalPrintFatalError("\nProcess is terminating due to StackOverflowException.\n");
RhFailFast();
}
bool isHandled = HardwareExceptionHandler(code, siginfo, context, siginfo->si_addr);
if (isHandled)
{
Expand DownExpand Up@@ -603,8 +589,7 @@ void SIGFPEHandler(int code, siginfo_t *siginfo, void *context)
// Initialize hardware exception handling
bool InitializeHardwareExceptionHandling()
{
// Run SIGSEGV handler on separate stack so we can handle stack overflow. Otherwise, the current (invalid) stack is used and another segfault is raised.
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV, SA_ONSTACK))
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV))
{
return false;
}
Expand All@@ -616,23 +601,23 @@ bool InitializeHardwareExceptionHandling()

#if defined(HOST_APPLE)
#ifndef HOST_TVOS // task_set_exception_ports is not supported on tvOS
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// checks in NativeAOT; continuing execution after LLDB traps an
// EXC_BAD_ACCESS will result in LLDB's EXC_BAD_ACCESS handler being
// invoked again. This also interferes with the translation of SIGFPEs
// to .NET-level ArithmeticExceptions. Work around this here by
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
ASSERT(kr == KERN_SUCCESS);
#endif
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/nativeaot/Runtime/unix/UnixSignals.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,11 +9,11 @@
#include "UnixSignals.h"

// Add handler for hardware exception signal
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags)
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction)
{
struct sigaction newAction;

newAction.sa_flags = SA_RESTART | additionalFlags;
newAction.sa_flags = SA_RESTART;
newAction.sa_handler = NULL;
newAction.sa_sigaction = handler;
newAction.sa_flags |= SA_SIGINFO;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/unix/UnixSignals.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,7 +14,7 @@

typedef void (*SignalHandler)(int code, siginfo_t* siginfo, void* context);

bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags = 0);
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction);
void RestoreSignalHandler(int signal_id, struct sigaction* previousAction);

#endif // __UNIX_SIGNALS_H__
2 changes: 1 addition & 1 deletion src/tests/Common/CoreCLRTestLibrary/Utilities.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ public static bool IsWindowsIoTCore

public static bool IsMonoRuntime => Type.GetType("Mono.RuntimeStructs") != null;
public static bool IsNotMonoRuntime => !IsMonoRuntime;
public static bool IsNativeAot => IsSingleFile && IsNotMonoRuntime && !IsReflectionEmitSupported;
public static bool IsNativeAot => IsNotMonoRuntime && !IsReflectionEmitSupported;

public static bool HasAssemblyFiles => !string.IsNullOrEmpty(typeof(Utilities).Assembly.Location);
public static bool IsSingleFile => !HasAssemblyFiles;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,8 +65,7 @@ struct LargeStruct65536
LargeStruct4096 se;
LargeStruct4096 sf;
}

internal class StackOverflow
class Program
{
[MethodImpl(MethodImplOptions.NoInlining)]
static void InfiniteRecursionA()
Expand DownExpand Up@@ -135,7 +134,7 @@ static void SecondaryThreadsTest(bool smallframe)
}
}

internal static void Run(string[] args)
static void Main(string[] args)
{
bool smallframe = (args[0] == "smallframe");
if (args[1] == "secondary")
Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>
<CLRTestKind>BuildOnly</CLRTestKind>

<Optimize>false</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow.cs" />
</ItemGroup>
</Project>

Original file line numberDiff line numberDiff line change
Expand Up@@ -2,16 +2,16 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;

namespace TestStackOverflow
namespace TestStackOverflow3
{
internal class StackOverflow3
class Program
{
private const int MAX_RECURSIVE_CALLS = 1000000;
static int ctr = 0;

public static void Run()
public static void Main()
{
StackOverflow3 ex = new StackOverflow3();
Program ex = new Program();
ex.Execute();
}

Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>

<Optimize>false</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLRTestKind>BuildOnly</CLRTestKind>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow3.cs" />
</ItemGroup>
</Project>

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/coreclr/nativeaot/Runtime/inc/CommonTypes.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,6 @@
#ifndef __COMMON_TYPES_H__
#define __COMMON_TYPES_H__

#include <assert.h>
#include <cstddef>
#include <cstdint>
#include <stdlib.h>
Expand Down
104 changes: 4 additions & 100 deletions src/coreclr/nativeaot/Runtime/thread.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,6 @@
#include "CommonTypes.h"
#include "CommonMacros.h"
#include "daccess.h"
#include "CommonMacros.inl"
#include "PalRedhawkCommon.h"
#include "PalRedhawk.h"
#include "rhassert.h"
Expand All@@ -28,11 +27,6 @@
#include "RhConfig.h"
#include "RhVolatile.h"

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
#include <signal.h>
#include <sys/mman.h>
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

#ifndef DACCESS_COMPILE

EXTERN_C NATIVEAOT_API void* REDHAWK_CALLCONV RhpHandleAlloc(void* pObject, int type);
Expand DownExpand Up@@ -287,9 +281,6 @@ void Thread::Construct()
if (StressLog::StressLogOn(~0u, 0))
m_pThreadStressLog = StressLog::CreateThreadStressLog(this);
#endif // STRESS_LOG
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
EnsureSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

// Everything else should be initialized to 0 via the static initialization of tls_CurrentThread.

Expand All@@ -306,89 +297,6 @@ void Thread::Construct()
ASSERT(m_interruptedContext == NULL);
}

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void Thread::FreeSignalAlternateStack()
{
void *altstack = m_alternateStack;
m_alternateStack = nullptr;

if (altstack != nullptr)
{
stack_t ss, oss;
// The man page for sigaltstack says that when the ss.ss_flags is set to SS_DISABLE,
// all other ss fields are ignored. However, MUSL implementation checks that the
// ss_size is >= MINSIGSTKSZ even in this case.
ss.ss_size = MINSIGSTKSZ;
ss.ss_flags = SS_DISABLE;
ss.ss_sp = NULL;
int st = sigaltstack(&ss, &oss);
if ((st == 0) && (oss.ss_flags != SS_DISABLE))
{
// Make sure this altstack is this PAL's before freeing.
if (oss.ss_sp == altstack)
{
int st = munmap(oss.ss_sp, oss.ss_size);
_ASSERTE(st == 0);
}
}
}
}

bool Thread::EnsureSignalAlternateStack()
{
int st = 0;

stack_t oss;

// Query the current alternate signal stack
st = sigaltstack(NULL, &oss);
if ((st == 0) && (oss.ss_flags == SS_DISABLE))
{
// There is no alternate stack for SIGSEGV handling installed yet so allocate one

// We include the size of the SignalHandlerWorkerReturnPoint in the alternate stack size since the
// context contained in it is large and the SIGSTKSZ was not sufficient on ARM64 during testing.
int altStackSize = SIGSTKSZ;
#ifdef HAS_ADDRESS_SANITIZER
// Asan also uses alternate stack so we increase its size on the SIGSTKSZ * 4 that enough for asan
// (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc)
altStackSize += SIGSTKSZ * 4;
#endif
altStackSize = ALIGN_UP(altStackSize, PalOsPageSize());
int flags = MAP_ANONYMOUS | MAP_PRIVATE;
#ifdef MAP_STACK
flags |= MAP_STACK;
#endif
void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, flags, -1, 0);
if (altStack != MAP_FAILED)
{
// create a guard page for the alternate stack
st = mprotect(altStack, PalOsPageSize(), PROT_NONE);
if (st == 0)
{
stack_t ss;
ss.ss_sp = (char*)altStack;
ss.ss_size = altStackSize;
ss.ss_flags = 0;
st = sigaltstack(&ss, NULL);
}

if (st == 0)
{
m_alternateStack = altStack;
}
else
{
int st2 = munmap(altStack, altStackSize);
_ASSERTE(st2 == 0);
}
}
}

return (st == 0);
}
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

bool Thread::IsInitialized()
{
return (m_ThreadStateFlags != TSF_Unknown);
Expand DownExpand Up@@ -453,10 +361,6 @@ void Thread::Destroy()
}
#endif //FEATURE_SUSPEND_REDIRECTION

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

ASSERT(m_pGCFrameRegistrations == NULL);
}

Expand DownExpand Up@@ -962,19 +866,19 @@ void Thread::Unhijack()
}

// This unhijack routine is called to undo a hijack, that is potentially on a different thread.
//
//
// Although there are many code sequences (here and in asm) to
// perform an unhijack operation, they will never execute concurrently:
//
//
// - A thread may unhijack itself at any time so long as it does that from unmanaged code while in coop mode.
// This ensures that coop thread can access its stack synchronously.
// Unhijacking from unmanaged code ensures that another thread will not attempt to hijack it,
// since we only hijack threads that are executing managed code.
//
//
// - A GC thread may access a thread asynchronously, including unhijacking it.
// Asynchronously accessed thread must be in preemptive mode and should not
// access the managed portion of its stack.
//
//
// - A thread that owns the suspension can access another thread as long as the other thread is
// in preemptive mode or suspended in managed code.
// Either way the other thread cannot be accessing its hijack.
Expand Down
12 changes: 2 additions & 10 deletions src/coreclr/nativeaot/Runtime/thread.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ struct ThreadBuffer
HANDLE m_hPalThread; // WARNING: this may legitimately be INVALID_HANDLE_VALUE
void ** m_ppvHijackedReturnAddressLocation;
void * m_pvHijackedReturnAddress;
uintptr_t m_uHijackedReturnValueFlags;
uintptr_t m_uHijackedReturnValueFlags;
PTR_ExInfo m_pExInfoStackHead;
Object* m_threadAbortException; // ThreadAbortException instance -set only during thread abort
Object* m_pThreadLocalStatics;
Expand All@@ -112,9 +112,6 @@ struct ThreadBuffer
#ifdef FEATURE_GC_STRESS
uint32_t m_uRand; // current per-thread random number
#endif // FEATURE_GC_STRESS
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void * m_alternateStack; // ptr to alternate signal stack
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

struct ReversePInvokeFrame
Expand DownExpand Up@@ -155,7 +152,7 @@ class Thread : private ThreadBuffer
// For suspension APCs it is mostly harmless, but wasteful and in extreme
// cases may force the target thread into stack oveflow.
// We use this flag to avoid sending another APC when one is still going through.
//
//
// On Unix this is an optimization to not queue up more signals when one is
// still being processed.
};
Expand DownExpand Up@@ -315,11 +312,6 @@ class Thread : private ThreadBuffer

bool IsActivationPending();
void SetActivationPending(bool isPending);

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
bool EnsureSignalAlternateStack();
void FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

#ifndef __GCENV_BASE_INCLUDED__
Expand Down
43 changes: 14 additions & 29 deletions src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,9 +11,6 @@
#include "HardwareExceptions.h"
#include "UnixSignals.h"
#include "PalCreateDump.h"
#include "thread.h"
#include "threadstore.h"
#include <sys/mman.h>

#if defined(HOST_APPLE)
#include <mach/mach.h>
Expand DownExpand Up@@ -548,17 +545,6 @@ bool HardwareExceptionHandler(int code, siginfo_t *siginfo, void *context, void*
// Handler for the SIGSEGV signal
void SIGSEGVHandler(int code, siginfo_t *siginfo, void *context)
{
// First check if we have a stack overflow
size_t sp = ((UNIX_CONTEXT *)context)->GetSp();
size_t failureAddress = (size_t)siginfo->si_addr;

// If the failure address is at most one page above or below the stack pointer,
// we have a stack overflow.
if ((failureAddress - (sp - PalOsPageSize())) < (size_t)PalOsPageSize() * 2)
{
PalPrintFatalError("\nProcess is terminating due to StackOverflowException.\n");
RhFailFast();
}
bool isHandled = HardwareExceptionHandler(code, siginfo, context, siginfo->si_addr);
if (isHandled)
{
Expand DownExpand Up@@ -603,8 +589,7 @@ void SIGFPEHandler(int code, siginfo_t *siginfo, void *context)
// Initialize hardware exception handling
bool InitializeHardwareExceptionHandling()
{
// Run SIGSEGV handler on separate stack so we can handle stack overflow. Otherwise, the current (invalid) stack is used and another segfault is raised.
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV, SA_ONSTACK))
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV))
{
return false;
}
Expand All@@ -616,23 +601,23 @@ bool InitializeHardwareExceptionHandling()

#if defined(HOST_APPLE)
#ifndef HOST_TVOS // task_set_exception_ports is not supported on tvOS
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// checks in NativeAOT; continuing execution after LLDB traps an
// EXC_BAD_ACCESS will result in LLDB's EXC_BAD_ACCESS handler being
// invoked again. This also interferes with the translation of SIGFPEs
// to .NET-level ArithmeticExceptions. Work around this here by
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
ASSERT(kr == KERN_SUCCESS);
#endif
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/nativeaot/Runtime/unix/UnixSignals.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,11 +9,11 @@
#include "UnixSignals.h"

// Add handler for hardware exception signal
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags)
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction)
{
struct sigaction newAction;

newAction.sa_flags = SA_RESTART | additionalFlags;
newAction.sa_flags = SA_RESTART;
newAction.sa_handler = NULL;
newAction.sa_sigaction = handler;
newAction.sa_flags |= SA_SIGINFO;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/unix/UnixSignals.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,7 +14,7 @@

typedef void (*SignalHandler)(int code, siginfo_t* siginfo, void* context);

bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags = 0);
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction);
void RestoreSignalHandler(int signal_id, struct sigaction* previousAction);

#endif // __UNIX_SIGNALS_H__
2 changes: 1 addition & 1 deletion src/tests/Common/CoreCLRTestLibrary/Utilities.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ public static bool IsWindowsIoTCore

public static bool IsMonoRuntime => Type.GetType("Mono.RuntimeStructs") != null;
public static bool IsNotMonoRuntime => !IsMonoRuntime;
public static bool IsNativeAot => IsSingleFile && IsNotMonoRuntime && !IsReflectionEmitSupported;
public static bool IsNativeAot => IsNotMonoRuntime && !IsReflectionEmitSupported;

public static bool HasAssemblyFiles => !string.IsNullOrEmpty(typeof(Utilities).Assembly.Location);
public static bool IsSingleFile => !HasAssemblyFiles;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,8 +65,7 @@ struct LargeStruct65536
LargeStruct4096 se;
LargeStruct4096 sf;
}

internal class StackOverflow
class Program
{
[MethodImpl(MethodImplOptions.NoInlining)]
static void InfiniteRecursionA()
Expand DownExpand Up@@ -135,7 +134,7 @@ static void SecondaryThreadsTest(bool smallframe)
}
}

internal static void Run(string[] args)
static void Main(string[] args)
{
bool smallframe = (args[0] == "smallframe");
if (args[1] == "secondary")
Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>
<CLRTestKind>BuildOnly</CLRTestKind>

<Optimize>false</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow.cs" />
</ItemGroup>
</Project>

Original file line numberDiff line numberDiff line change
Expand Up@@ -2,16 +2,16 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;

namespace TestStackOverflow
namespace TestStackOverflow3
{
internal class StackOverflow3
class Program
{
private const int MAX_RECURSIVE_CALLS = 1000000;
static int ctr = 0;

public static void Run()
public static void Main()
{
StackOverflow3 ex = new StackOverflow3();
Program ex = new Program();
ex.Execute();
}

Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>

<Optimize>false</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLRTestKind>BuildOnly</CLRTestKind>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow3.cs" />
</ItemGroup>
</Project>

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/coreclr/nativeaot/Runtime/inc/CommonTypes.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,6 @@
#ifndef __COMMON_TYPES_H__
#define __COMMON_TYPES_H__

#include <assert.h>
#include <cstddef>
#include <cstdint>
#include <stdlib.h>
Expand Down
104 changes: 4 additions & 100 deletions src/coreclr/nativeaot/Runtime/thread.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,6 @@
#include "CommonTypes.h"
#include "CommonMacros.h"
#include "daccess.h"
#include "CommonMacros.inl"
#include "PalRedhawkCommon.h"
#include "PalRedhawk.h"
#include "rhassert.h"
Expand All@@ -28,11 +27,6 @@
#include "RhConfig.h"
#include "RhVolatile.h"

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
#include <signal.h>
#include <sys/mman.h>
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

#ifndef DACCESS_COMPILE

EXTERN_C NATIVEAOT_API void* REDHAWK_CALLCONV RhpHandleAlloc(void* pObject, int type);
Expand DownExpand Up@@ -287,9 +281,6 @@ void Thread::Construct()
if (StressLog::StressLogOn(~0u, 0))
m_pThreadStressLog = StressLog::CreateThreadStressLog(this);
#endif // STRESS_LOG
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
EnsureSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

// Everything else should be initialized to 0 via the static initialization of tls_CurrentThread.

Expand All@@ -306,89 +297,6 @@ void Thread::Construct()
ASSERT(m_interruptedContext == NULL);
}

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void Thread::FreeSignalAlternateStack()
{
void *altstack = m_alternateStack;
m_alternateStack = nullptr;

if (altstack != nullptr)
{
stack_t ss, oss;
// The man page for sigaltstack says that when the ss.ss_flags is set to SS_DISABLE,
// all other ss fields are ignored. However, MUSL implementation checks that the
// ss_size is >= MINSIGSTKSZ even in this case.
ss.ss_size = MINSIGSTKSZ;
ss.ss_flags = SS_DISABLE;
ss.ss_sp = NULL;
int st = sigaltstack(&ss, &oss);
if ((st == 0) && (oss.ss_flags != SS_DISABLE))
{
// Make sure this altstack is this PAL's before freeing.
if (oss.ss_sp == altstack)
{
int st = munmap(oss.ss_sp, oss.ss_size);
_ASSERTE(st == 0);
}
}
}
}

bool Thread::EnsureSignalAlternateStack()
{
int st = 0;

stack_t oss;

// Query the current alternate signal stack
st = sigaltstack(NULL, &oss);
if ((st == 0) && (oss.ss_flags == SS_DISABLE))
{
// There is no alternate stack for SIGSEGV handling installed yet so allocate one

// We include the size of the SignalHandlerWorkerReturnPoint in the alternate stack size since the
// context contained in it is large and the SIGSTKSZ was not sufficient on ARM64 during testing.
int altStackSize = SIGSTKSZ;
#ifdef HAS_ADDRESS_SANITIZER
// Asan also uses alternate stack so we increase its size on the SIGSTKSZ * 4 that enough for asan
// (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc)
altStackSize += SIGSTKSZ * 4;
#endif
altStackSize = ALIGN_UP(altStackSize, PalOsPageSize());
int flags = MAP_ANONYMOUS | MAP_PRIVATE;
#ifdef MAP_STACK
flags |= MAP_STACK;
#endif
void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, flags, -1, 0);
if (altStack != MAP_FAILED)
{
// create a guard page for the alternate stack
st = mprotect(altStack, PalOsPageSize(), PROT_NONE);
if (st == 0)
{
stack_t ss;
ss.ss_sp = (char*)altStack;
ss.ss_size = altStackSize;
ss.ss_flags = 0;
st = sigaltstack(&ss, NULL);
}

if (st == 0)
{
m_alternateStack = altStack;
}
else
{
int st2 = munmap(altStack, altStackSize);
_ASSERTE(st2 == 0);
}
}
}

return (st == 0);
}
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

bool Thread::IsInitialized()
{
return (m_ThreadStateFlags != TSF_Unknown);
Expand DownExpand Up@@ -453,10 +361,6 @@ void Thread::Destroy()
}
#endif //FEATURE_SUSPEND_REDIRECTION

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

ASSERT(m_pGCFrameRegistrations == NULL);
}

Expand DownExpand Up@@ -962,19 +866,19 @@ void Thread::Unhijack()
}

// This unhijack routine is called to undo a hijack, that is potentially on a different thread.
//
//
// Although there are many code sequences (here and in asm) to
// perform an unhijack operation, they will never execute concurrently:
//
//
// - A thread may unhijack itself at any time so long as it does that from unmanaged code while in coop mode.
// This ensures that coop thread can access its stack synchronously.
// Unhijacking from unmanaged code ensures that another thread will not attempt to hijack it,
// since we only hijack threads that are executing managed code.
//
//
// - A GC thread may access a thread asynchronously, including unhijacking it.
// Asynchronously accessed thread must be in preemptive mode and should not
// access the managed portion of its stack.
//
//
// - A thread that owns the suspension can access another thread as long as the other thread is
// in preemptive mode or suspended in managed code.
// Either way the other thread cannot be accessing its hijack.
Expand Down
12 changes: 2 additions & 10 deletions src/coreclr/nativeaot/Runtime/thread.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ struct ThreadBuffer
HANDLE m_hPalThread; // WARNING: this may legitimately be INVALID_HANDLE_VALUE
void ** m_ppvHijackedReturnAddressLocation;
void * m_pvHijackedReturnAddress;
uintptr_t m_uHijackedReturnValueFlags;
uintptr_t m_uHijackedReturnValueFlags;
PTR_ExInfo m_pExInfoStackHead;
Object* m_threadAbortException; // ThreadAbortException instance -set only during thread abort
Object* m_pThreadLocalStatics;
Expand All@@ -112,9 +112,6 @@ struct ThreadBuffer
#ifdef FEATURE_GC_STRESS
uint32_t m_uRand; // current per-thread random number
#endif // FEATURE_GC_STRESS
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void * m_alternateStack; // ptr to alternate signal stack
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

struct ReversePInvokeFrame
Expand DownExpand Up@@ -155,7 +152,7 @@ class Thread : private ThreadBuffer
// For suspension APCs it is mostly harmless, but wasteful and in extreme
// cases may force the target thread into stack oveflow.
// We use this flag to avoid sending another APC when one is still going through.
//
//
// On Unix this is an optimization to not queue up more signals when one is
// still being processed.
};
Expand DownExpand Up@@ -315,11 +312,6 @@ class Thread : private ThreadBuffer

bool IsActivationPending();
void SetActivationPending(bool isPending);

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
bool EnsureSignalAlternateStack();
void FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

#ifndef __GCENV_BASE_INCLUDED__
Expand Down
43 changes: 14 additions & 29 deletions src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,9 +11,6 @@
#include "HardwareExceptions.h"
#include "UnixSignals.h"
#include "PalCreateDump.h"
#include "thread.h"
#include "threadstore.h"
#include <sys/mman.h>

#if defined(HOST_APPLE)
#include <mach/mach.h>
Expand DownExpand Up@@ -548,17 +545,6 @@ bool HardwareExceptionHandler(int code, siginfo_t *siginfo, void *context, void*
// Handler for the SIGSEGV signal
void SIGSEGVHandler(int code, siginfo_t *siginfo, void *context)
{
// First check if we have a stack overflow
size_t sp = ((UNIX_CONTEXT *)context)->GetSp();
size_t failureAddress = (size_t)siginfo->si_addr;

// If the failure address is at most one page above or below the stack pointer,
// we have a stack overflow.
if ((failureAddress - (sp - PalOsPageSize())) < (size_t)PalOsPageSize() * 2)
{
PalPrintFatalError("\nProcess is terminating due to StackOverflowException.\n");
RhFailFast();
}
bool isHandled = HardwareExceptionHandler(code, siginfo, context, siginfo->si_addr);
if (isHandled)
{
Expand DownExpand Up@@ -603,8 +589,7 @@ void SIGFPEHandler(int code, siginfo_t *siginfo, void *context)
// Initialize hardware exception handling
bool InitializeHardwareExceptionHandling()
{
// Run SIGSEGV handler on separate stack so we can handle stack overflow. Otherwise, the current (invalid) stack is used and another segfault is raised.
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV, SA_ONSTACK))
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV))
{
return false;
}
Expand All@@ -616,23 +601,23 @@ bool InitializeHardwareExceptionHandling()

#if defined(HOST_APPLE)
#ifndef HOST_TVOS // task_set_exception_ports is not supported on tvOS
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// checks in NativeAOT; continuing execution after LLDB traps an
// EXC_BAD_ACCESS will result in LLDB's EXC_BAD_ACCESS handler being
// invoked again. This also interferes with the translation of SIGFPEs
// to .NET-level ArithmeticExceptions. Work around this here by
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
ASSERT(kr == KERN_SUCCESS);
#endif
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/nativeaot/Runtime/unix/UnixSignals.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,11 +9,11 @@
#include "UnixSignals.h"

// Add handler for hardware exception signal
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags)
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction)
{
struct sigaction newAction;

newAction.sa_flags = SA_RESTART | additionalFlags;
newAction.sa_flags = SA_RESTART;
newAction.sa_handler = NULL;
newAction.sa_sigaction = handler;
newAction.sa_flags |= SA_SIGINFO;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/unix/UnixSignals.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,7 +14,7 @@

typedef void (*SignalHandler)(int code, siginfo_t* siginfo, void* context);

bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags = 0);
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction);
void RestoreSignalHandler(int signal_id, struct sigaction* previousAction);

#endif // __UNIX_SIGNALS_H__
2 changes: 1 addition & 1 deletion src/tests/Common/CoreCLRTestLibrary/Utilities.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ public static bool IsWindowsIoTCore

public static bool IsMonoRuntime => Type.GetType("Mono.RuntimeStructs") != null;
public static bool IsNotMonoRuntime => !IsMonoRuntime;
public static bool IsNativeAot => IsSingleFile && IsNotMonoRuntime && !IsReflectionEmitSupported;
public static bool IsNativeAot => IsNotMonoRuntime && !IsReflectionEmitSupported;

public static bool HasAssemblyFiles => !string.IsNullOrEmpty(typeof(Utilities).Assembly.Location);
public static bool IsSingleFile => !HasAssemblyFiles;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,8 +65,7 @@ struct LargeStruct65536
LargeStruct4096 se;
LargeStruct4096 sf;
}

internal class StackOverflow
class Program
{
[MethodImpl(MethodImplOptions.NoInlining)]
static void InfiniteRecursionA()
Expand DownExpand Up@@ -135,7 +134,7 @@ static void SecondaryThreadsTest(bool smallframe)
}
}

internal static void Run(string[] args)
static void Main(string[] args)
{
bool smallframe = (args[0] == "smallframe");
if (args[1] == "secondary")
Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>
<CLRTestKind>BuildOnly</CLRTestKind>

<Optimize>false</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow.cs" />
</ItemGroup>
</Project>

Original file line numberDiff line numberDiff line change
Expand Up@@ -2,16 +2,16 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;

namespace TestStackOverflow
namespace TestStackOverflow3
{
internal class StackOverflow3
class Program
{
private const int MAX_RECURSIVE_CALLS = 1000000;
static int ctr = 0;

public static void Run()
public static void Main()
{
StackOverflow3 ex = new StackOverflow3();
Program ex = new Program();
ex.Execute();
}

Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>

<Optimize>false</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLRTestKind>BuildOnly</CLRTestKind>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow3.cs" />
</ItemGroup>
</Project>

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/coreclr/nativeaot/Runtime/inc/CommonTypes.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,6 @@
#ifndef __COMMON_TYPES_H__
#define __COMMON_TYPES_H__

#include <assert.h>
#include <cstddef>
#include <cstdint>
#include <stdlib.h>
Expand Down
104 changes: 4 additions & 100 deletions src/coreclr/nativeaot/Runtime/thread.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,6 @@
#include "CommonTypes.h"
#include "CommonMacros.h"
#include "daccess.h"
#include "CommonMacros.inl"
#include "PalRedhawkCommon.h"
#include "PalRedhawk.h"
#include "rhassert.h"
Expand All@@ -28,11 +27,6 @@
#include "RhConfig.h"
#include "RhVolatile.h"

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
#include <signal.h>
#include <sys/mman.h>
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

#ifndef DACCESS_COMPILE

EXTERN_C NATIVEAOT_API void* REDHAWK_CALLCONV RhpHandleAlloc(void* pObject, int type);
Expand DownExpand Up@@ -287,9 +281,6 @@ void Thread::Construct()
if (StressLog::StressLogOn(~0u, 0))
m_pThreadStressLog = StressLog::CreateThreadStressLog(this);
#endif // STRESS_LOG
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
EnsureSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

// Everything else should be initialized to 0 via the static initialization of tls_CurrentThread.

Expand All@@ -306,89 +297,6 @@ void Thread::Construct()
ASSERT(m_interruptedContext == NULL);
}

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void Thread::FreeSignalAlternateStack()
{
void *altstack = m_alternateStack;
m_alternateStack = nullptr;

if (altstack != nullptr)
{
stack_t ss, oss;
// The man page for sigaltstack says that when the ss.ss_flags is set to SS_DISABLE,
// all other ss fields are ignored. However, MUSL implementation checks that the
// ss_size is >= MINSIGSTKSZ even in this case.
ss.ss_size = MINSIGSTKSZ;
ss.ss_flags = SS_DISABLE;
ss.ss_sp = NULL;
int st = sigaltstack(&ss, &oss);
if ((st == 0) && (oss.ss_flags != SS_DISABLE))
{
// Make sure this altstack is this PAL's before freeing.
if (oss.ss_sp == altstack)
{
int st = munmap(oss.ss_sp, oss.ss_size);
_ASSERTE(st == 0);
}
}
}
}

bool Thread::EnsureSignalAlternateStack()
{
int st = 0;

stack_t oss;

// Query the current alternate signal stack
st = sigaltstack(NULL, &oss);
if ((st == 0) && (oss.ss_flags == SS_DISABLE))
{
// There is no alternate stack for SIGSEGV handling installed yet so allocate one

// We include the size of the SignalHandlerWorkerReturnPoint in the alternate stack size since the
// context contained in it is large and the SIGSTKSZ was not sufficient on ARM64 during testing.
int altStackSize = SIGSTKSZ;
#ifdef HAS_ADDRESS_SANITIZER
// Asan also uses alternate stack so we increase its size on the SIGSTKSZ * 4 that enough for asan
// (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc)
altStackSize += SIGSTKSZ * 4;
#endif
altStackSize = ALIGN_UP(altStackSize, PalOsPageSize());
int flags = MAP_ANONYMOUS | MAP_PRIVATE;
#ifdef MAP_STACK
flags |= MAP_STACK;
#endif
void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, flags, -1, 0);
if (altStack != MAP_FAILED)
{
// create a guard page for the alternate stack
st = mprotect(altStack, PalOsPageSize(), PROT_NONE);
if (st == 0)
{
stack_t ss;
ss.ss_sp = (char*)altStack;
ss.ss_size = altStackSize;
ss.ss_flags = 0;
st = sigaltstack(&ss, NULL);
}

if (st == 0)
{
m_alternateStack = altStack;
}
else
{
int st2 = munmap(altStack, altStackSize);
_ASSERTE(st2 == 0);
}
}
}

return (st == 0);
}
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

bool Thread::IsInitialized()
{
return (m_ThreadStateFlags != TSF_Unknown);
Expand DownExpand Up@@ -453,10 +361,6 @@ void Thread::Destroy()
}
#endif //FEATURE_SUSPEND_REDIRECTION

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

ASSERT(m_pGCFrameRegistrations == NULL);
}

Expand DownExpand Up@@ -962,19 +866,19 @@ void Thread::Unhijack()
}

// This unhijack routine is called to undo a hijack, that is potentially on a different thread.
//
//
// Although there are many code sequences (here and in asm) to
// perform an unhijack operation, they will never execute concurrently:
//
//
// - A thread may unhijack itself at any time so long as it does that from unmanaged code while in coop mode.
// This ensures that coop thread can access its stack synchronously.
// Unhijacking from unmanaged code ensures that another thread will not attempt to hijack it,
// since we only hijack threads that are executing managed code.
//
//
// - A GC thread may access a thread asynchronously, including unhijacking it.
// Asynchronously accessed thread must be in preemptive mode and should not
// access the managed portion of its stack.
//
//
// - A thread that owns the suspension can access another thread as long as the other thread is
// in preemptive mode or suspended in managed code.
// Either way the other thread cannot be accessing its hijack.
Expand Down
12 changes: 2 additions & 10 deletions src/coreclr/nativeaot/Runtime/thread.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ struct ThreadBuffer
HANDLE m_hPalThread; // WARNING: this may legitimately be INVALID_HANDLE_VALUE
void ** m_ppvHijackedReturnAddressLocation;
void * m_pvHijackedReturnAddress;
uintptr_t m_uHijackedReturnValueFlags;
uintptr_t m_uHijackedReturnValueFlags;
PTR_ExInfo m_pExInfoStackHead;
Object* m_threadAbortException; // ThreadAbortException instance -set only during thread abort
Object* m_pThreadLocalStatics;
Expand All@@ -112,9 +112,6 @@ struct ThreadBuffer
#ifdef FEATURE_GC_STRESS
uint32_t m_uRand; // current per-thread random number
#endif // FEATURE_GC_STRESS
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void * m_alternateStack; // ptr to alternate signal stack
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

struct ReversePInvokeFrame
Expand DownExpand Up@@ -155,7 +152,7 @@ class Thread : private ThreadBuffer
// For suspension APCs it is mostly harmless, but wasteful and in extreme
// cases may force the target thread into stack oveflow.
// We use this flag to avoid sending another APC when one is still going through.
//
//
// On Unix this is an optimization to not queue up more signals when one is
// still being processed.
};
Expand DownExpand Up@@ -315,11 +312,6 @@ class Thread : private ThreadBuffer

bool IsActivationPending();
void SetActivationPending(bool isPending);

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
bool EnsureSignalAlternateStack();
void FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

#ifndef __GCENV_BASE_INCLUDED__
Expand Down
43 changes: 14 additions & 29 deletions src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,9 +11,6 @@
#include "HardwareExceptions.h"
#include "UnixSignals.h"
#include "PalCreateDump.h"
#include "thread.h"
#include "threadstore.h"
#include <sys/mman.h>

#if defined(HOST_APPLE)
#include <mach/mach.h>
Expand DownExpand Up@@ -548,17 +545,6 @@ bool HardwareExceptionHandler(int code, siginfo_t *siginfo, void *context, void*
// Handler for the SIGSEGV signal
void SIGSEGVHandler(int code, siginfo_t *siginfo, void *context)
{
// First check if we have a stack overflow
size_t sp = ((UNIX_CONTEXT *)context)->GetSp();
size_t failureAddress = (size_t)siginfo->si_addr;

// If the failure address is at most one page above or below the stack pointer,
// we have a stack overflow.
if ((failureAddress - (sp - PalOsPageSize())) < (size_t)PalOsPageSize() * 2)
{
PalPrintFatalError("\nProcess is terminating due to StackOverflowException.\n");
RhFailFast();
}
bool isHandled = HardwareExceptionHandler(code, siginfo, context, siginfo->si_addr);
if (isHandled)
{
Expand DownExpand Up@@ -603,8 +589,7 @@ void SIGFPEHandler(int code, siginfo_t *siginfo, void *context)
// Initialize hardware exception handling
bool InitializeHardwareExceptionHandling()
{
// Run SIGSEGV handler on separate stack so we can handle stack overflow. Otherwise, the current (invalid) stack is used and another segfault is raised.
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV, SA_ONSTACK))
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV))
{
return false;
}
Expand All@@ -616,23 +601,23 @@ bool InitializeHardwareExceptionHandling()

#if defined(HOST_APPLE)
#ifndef HOST_TVOS // task_set_exception_ports is not supported on tvOS
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// checks in NativeAOT; continuing execution after LLDB traps an
// EXC_BAD_ACCESS will result in LLDB's EXC_BAD_ACCESS handler being
// invoked again. This also interferes with the translation of SIGFPEs
// to .NET-level ArithmeticExceptions. Work around this here by
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
ASSERT(kr == KERN_SUCCESS);
#endif
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/nativeaot/Runtime/unix/UnixSignals.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,11 +9,11 @@
#include "UnixSignals.h"

// Add handler for hardware exception signal
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags)
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction)
{
struct sigaction newAction;

newAction.sa_flags = SA_RESTART | additionalFlags;
newAction.sa_flags = SA_RESTART;
newAction.sa_handler = NULL;
newAction.sa_sigaction = handler;
newAction.sa_flags |= SA_SIGINFO;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/unix/UnixSignals.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,7 +14,7 @@

typedef void (*SignalHandler)(int code, siginfo_t* siginfo, void* context);

bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags = 0);
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction);
void RestoreSignalHandler(int signal_id, struct sigaction* previousAction);

#endif // __UNIX_SIGNALS_H__
2 changes: 1 addition & 1 deletion src/tests/Common/CoreCLRTestLibrary/Utilities.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ public static bool IsWindowsIoTCore

public static bool IsMonoRuntime => Type.GetType("Mono.RuntimeStructs") != null;
public static bool IsNotMonoRuntime => !IsMonoRuntime;
public static bool IsNativeAot => IsSingleFile && IsNotMonoRuntime && !IsReflectionEmitSupported;
public static bool IsNativeAot => IsNotMonoRuntime && !IsReflectionEmitSupported;

public static bool HasAssemblyFiles => !string.IsNullOrEmpty(typeof(Utilities).Assembly.Location);
public static bool IsSingleFile => !HasAssemblyFiles;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,8 +65,7 @@ struct LargeStruct65536
LargeStruct4096 se;
LargeStruct4096 sf;
}

internal class StackOverflow
class Program
{
[MethodImpl(MethodImplOptions.NoInlining)]
static void InfiniteRecursionA()
Expand DownExpand Up@@ -135,7 +134,7 @@ static void SecondaryThreadsTest(bool smallframe)
}
}

internal static void Run(string[] args)
static void Main(string[] args)
{
bool smallframe = (args[0] == "smallframe");
if (args[1] == "secondary")
Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>
<CLRTestKind>BuildOnly</CLRTestKind>

<Optimize>false</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow.cs" />
</ItemGroup>
</Project>

Original file line numberDiff line numberDiff line change
Expand Up@@ -2,16 +2,16 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;

namespace TestStackOverflow
namespace TestStackOverflow3
{
internal class StackOverflow3
class Program
{
private const int MAX_RECURSIVE_CALLS = 1000000;
static int ctr = 0;

public static void Run()
public static void Main()
{
StackOverflow3 ex = new StackOverflow3();
Program ex = new Program();
ex.Execute();
}

Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>

<Optimize>false</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLRTestKind>BuildOnly</CLRTestKind>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow3.cs" />
</ItemGroup>
</Project>

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/coreclr/nativeaot/Runtime/inc/CommonTypes.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,6 @@
#ifndef __COMMON_TYPES_H__
#define __COMMON_TYPES_H__

#include <assert.h>
#include <cstddef>
#include <cstdint>
#include <stdlib.h>
Expand Down
104 changes: 4 additions & 100 deletions src/coreclr/nativeaot/Runtime/thread.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,6 @@
#include "CommonTypes.h"
#include "CommonMacros.h"
#include "daccess.h"
#include "CommonMacros.inl"
#include "PalRedhawkCommon.h"
#include "PalRedhawk.h"
#include "rhassert.h"
Expand All@@ -28,11 +27,6 @@
#include "RhConfig.h"
#include "RhVolatile.h"

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
#include <signal.h>
#include <sys/mman.h>
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

#ifndef DACCESS_COMPILE

EXTERN_C NATIVEAOT_API void* REDHAWK_CALLCONV RhpHandleAlloc(void* pObject, int type);
Expand DownExpand Up@@ -287,9 +281,6 @@ void Thread::Construct()
if (StressLog::StressLogOn(~0u, 0))
m_pThreadStressLog = StressLog::CreateThreadStressLog(this);
#endif // STRESS_LOG
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
EnsureSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

// Everything else should be initialized to 0 via the static initialization of tls_CurrentThread.

Expand All@@ -306,89 +297,6 @@ void Thread::Construct()
ASSERT(m_interruptedContext == NULL);
}

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void Thread::FreeSignalAlternateStack()
{
void *altstack = m_alternateStack;
m_alternateStack = nullptr;

if (altstack != nullptr)
{
stack_t ss, oss;
// The man page for sigaltstack says that when the ss.ss_flags is set to SS_DISABLE,
// all other ss fields are ignored. However, MUSL implementation checks that the
// ss_size is >= MINSIGSTKSZ even in this case.
ss.ss_size = MINSIGSTKSZ;
ss.ss_flags = SS_DISABLE;
ss.ss_sp = NULL;
int st = sigaltstack(&ss, &oss);
if ((st == 0) && (oss.ss_flags != SS_DISABLE))
{
// Make sure this altstack is this PAL's before freeing.
if (oss.ss_sp == altstack)
{
int st = munmap(oss.ss_sp, oss.ss_size);
_ASSERTE(st == 0);
}
}
}
}

bool Thread::EnsureSignalAlternateStack()
{
int st = 0;

stack_t oss;

// Query the current alternate signal stack
st = sigaltstack(NULL, &oss);
if ((st == 0) && (oss.ss_flags == SS_DISABLE))
{
// There is no alternate stack for SIGSEGV handling installed yet so allocate one

// We include the size of the SignalHandlerWorkerReturnPoint in the alternate stack size since the
// context contained in it is large and the SIGSTKSZ was not sufficient on ARM64 during testing.
int altStackSize = SIGSTKSZ;
#ifdef HAS_ADDRESS_SANITIZER
// Asan also uses alternate stack so we increase its size on the SIGSTKSZ * 4 that enough for asan
// (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc)
altStackSize += SIGSTKSZ * 4;
#endif
altStackSize = ALIGN_UP(altStackSize, PalOsPageSize());
int flags = MAP_ANONYMOUS | MAP_PRIVATE;
#ifdef MAP_STACK
flags |= MAP_STACK;
#endif
void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, flags, -1, 0);
if (altStack != MAP_FAILED)
{
// create a guard page for the alternate stack
st = mprotect(altStack, PalOsPageSize(), PROT_NONE);
if (st == 0)
{
stack_t ss;
ss.ss_sp = (char*)altStack;
ss.ss_size = altStackSize;
ss.ss_flags = 0;
st = sigaltstack(&ss, NULL);
}

if (st == 0)
{
m_alternateStack = altStack;
}
else
{
int st2 = munmap(altStack, altStackSize);
_ASSERTE(st2 == 0);
}
}
}

return (st == 0);
}
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

bool Thread::IsInitialized()
{
return (m_ThreadStateFlags != TSF_Unknown);
Expand DownExpand Up@@ -453,10 +361,6 @@ void Thread::Destroy()
}
#endif //FEATURE_SUSPEND_REDIRECTION

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

ASSERT(m_pGCFrameRegistrations == NULL);
}

Expand DownExpand Up@@ -962,19 +866,19 @@ void Thread::Unhijack()
}

// This unhijack routine is called to undo a hijack, that is potentially on a different thread.
//
//
// Although there are many code sequences (here and in asm) to
// perform an unhijack operation, they will never execute concurrently:
//
//
// - A thread may unhijack itself at any time so long as it does that from unmanaged code while in coop mode.
// This ensures that coop thread can access its stack synchronously.
// Unhijacking from unmanaged code ensures that another thread will not attempt to hijack it,
// since we only hijack threads that are executing managed code.
//
//
// - A GC thread may access a thread asynchronously, including unhijacking it.
// Asynchronously accessed thread must be in preemptive mode and should not
// access the managed portion of its stack.
//
//
// - A thread that owns the suspension can access another thread as long as the other thread is
// in preemptive mode or suspended in managed code.
// Either way the other thread cannot be accessing its hijack.
Expand Down
12 changes: 2 additions & 10 deletions src/coreclr/nativeaot/Runtime/thread.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ struct ThreadBuffer
HANDLE m_hPalThread; // WARNING: this may legitimately be INVALID_HANDLE_VALUE
void ** m_ppvHijackedReturnAddressLocation;
void * m_pvHijackedReturnAddress;
uintptr_t m_uHijackedReturnValueFlags;
uintptr_t m_uHijackedReturnValueFlags;
PTR_ExInfo m_pExInfoStackHead;
Object* m_threadAbortException; // ThreadAbortException instance -set only during thread abort
Object* m_pThreadLocalStatics;
Expand All@@ -112,9 +112,6 @@ struct ThreadBuffer
#ifdef FEATURE_GC_STRESS
uint32_t m_uRand; // current per-thread random number
#endif // FEATURE_GC_STRESS
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void * m_alternateStack; // ptr to alternate signal stack
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

struct ReversePInvokeFrame
Expand DownExpand Up@@ -155,7 +152,7 @@ class Thread : private ThreadBuffer
// For suspension APCs it is mostly harmless, but wasteful and in extreme
// cases may force the target thread into stack oveflow.
// We use this flag to avoid sending another APC when one is still going through.
//
//
// On Unix this is an optimization to not queue up more signals when one is
// still being processed.
};
Expand DownExpand Up@@ -315,11 +312,6 @@ class Thread : private ThreadBuffer

bool IsActivationPending();
void SetActivationPending(bool isPending);

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
bool EnsureSignalAlternateStack();
void FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

#ifndef __GCENV_BASE_INCLUDED__
Expand Down
43 changes: 14 additions & 29 deletions src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,9 +11,6 @@
#include "HardwareExceptions.h"
#include "UnixSignals.h"
#include "PalCreateDump.h"
#include "thread.h"
#include "threadstore.h"
#include <sys/mman.h>

#if defined(HOST_APPLE)
#include <mach/mach.h>
Expand DownExpand Up@@ -548,17 +545,6 @@ bool HardwareExceptionHandler(int code, siginfo_t *siginfo, void *context, void*
// Handler for the SIGSEGV signal
void SIGSEGVHandler(int code, siginfo_t *siginfo, void *context)
{
// First check if we have a stack overflow
size_t sp = ((UNIX_CONTEXT *)context)->GetSp();
size_t failureAddress = (size_t)siginfo->si_addr;

// If the failure address is at most one page above or below the stack pointer,
// we have a stack overflow.
if ((failureAddress - (sp - PalOsPageSize())) < (size_t)PalOsPageSize() * 2)
{
PalPrintFatalError("\nProcess is terminating due to StackOverflowException.\n");
RhFailFast();
}
bool isHandled = HardwareExceptionHandler(code, siginfo, context, siginfo->si_addr);
if (isHandled)
{
Expand DownExpand Up@@ -603,8 +589,7 @@ void SIGFPEHandler(int code, siginfo_t *siginfo, void *context)
// Initialize hardware exception handling
bool InitializeHardwareExceptionHandling()
{
// Run SIGSEGV handler on separate stack so we can handle stack overflow. Otherwise, the current (invalid) stack is used and another segfault is raised.
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV, SA_ONSTACK))
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV))
{
return false;
}
Expand All@@ -616,23 +601,23 @@ bool InitializeHardwareExceptionHandling()

#if defined(HOST_APPLE)
#ifndef HOST_TVOS // task_set_exception_ports is not supported on tvOS
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// checks in NativeAOT; continuing execution after LLDB traps an
// EXC_BAD_ACCESS will result in LLDB's EXC_BAD_ACCESS handler being
// invoked again. This also interferes with the translation of SIGFPEs
// to .NET-level ArithmeticExceptions. Work around this here by
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
ASSERT(kr == KERN_SUCCESS);
#endif
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/nativeaot/Runtime/unix/UnixSignals.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,11 +9,11 @@
#include "UnixSignals.h"

// Add handler for hardware exception signal
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags)
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction)
{
struct sigaction newAction;

newAction.sa_flags = SA_RESTART | additionalFlags;
newAction.sa_flags = SA_RESTART;
newAction.sa_handler = NULL;
newAction.sa_sigaction = handler;
newAction.sa_flags |= SA_SIGINFO;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/unix/UnixSignals.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,7 +14,7 @@

typedef void (*SignalHandler)(int code, siginfo_t* siginfo, void* context);

bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags = 0);
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction);
void RestoreSignalHandler(int signal_id, struct sigaction* previousAction);

#endif // __UNIX_SIGNALS_H__
2 changes: 1 addition & 1 deletion src/tests/Common/CoreCLRTestLibrary/Utilities.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ public static bool IsWindowsIoTCore

public static bool IsMonoRuntime => Type.GetType("Mono.RuntimeStructs") != null;
public static bool IsNotMonoRuntime => !IsMonoRuntime;
public static bool IsNativeAot => IsSingleFile && IsNotMonoRuntime && !IsReflectionEmitSupported;
public static bool IsNativeAot => IsNotMonoRuntime && !IsReflectionEmitSupported;

public static bool HasAssemblyFiles => !string.IsNullOrEmpty(typeof(Utilities).Assembly.Location);
public static bool IsSingleFile => !HasAssemblyFiles;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,8 +65,7 @@ struct LargeStruct65536
LargeStruct4096 se;
LargeStruct4096 sf;
}

internal class StackOverflow
class Program
{
[MethodImpl(MethodImplOptions.NoInlining)]
static void InfiniteRecursionA()
Expand DownExpand Up@@ -135,7 +134,7 @@ static void SecondaryThreadsTest(bool smallframe)
}
}

internal static void Run(string[] args)
static void Main(string[] args)
{
bool smallframe = (args[0] == "smallframe");
if (args[1] == "secondary")
Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>
<CLRTestKind>BuildOnly</CLRTestKind>

<Optimize>false</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow.cs" />
</ItemGroup>
</Project>

Original file line numberDiff line numberDiff line change
Expand Up@@ -2,16 +2,16 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;

namespace TestStackOverflow
namespace TestStackOverflow3
{
internal class StackOverflow3
class Program
{
private const int MAX_RECURSIVE_CALLS = 1000000;
static int ctr = 0;

public static void Run()
public static void Main()
{
StackOverflow3 ex = new StackOverflow3();
Program ex = new Program();
ex.Execute();
}

Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>

<Optimize>false</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLRTestKind>BuildOnly</CLRTestKind>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow3.cs" />
</ItemGroup>
</Project>

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/coreclr/nativeaot/Runtime/inc/CommonTypes.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,6 @@
#ifndef __COMMON_TYPES_H__
#define __COMMON_TYPES_H__

#include <assert.h>
#include <cstddef>
#include <cstdint>
#include <stdlib.h>
Expand Down
104 changes: 4 additions & 100 deletions src/coreclr/nativeaot/Runtime/thread.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,6 @@
#include "CommonTypes.h"
#include "CommonMacros.h"
#include "daccess.h"
#include "CommonMacros.inl"
#include "PalRedhawkCommon.h"
#include "PalRedhawk.h"
#include "rhassert.h"
Expand All@@ -28,11 +27,6 @@
#include "RhConfig.h"
#include "RhVolatile.h"

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
#include <signal.h>
#include <sys/mman.h>
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

#ifndef DACCESS_COMPILE

EXTERN_C NATIVEAOT_API void* REDHAWK_CALLCONV RhpHandleAlloc(void* pObject, int type);
Expand DownExpand Up@@ -287,9 +281,6 @@ void Thread::Construct()
if (StressLog::StressLogOn(~0u, 0))
m_pThreadStressLog = StressLog::CreateThreadStressLog(this);
#endif // STRESS_LOG
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
EnsureSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

// Everything else should be initialized to 0 via the static initialization of tls_CurrentThread.

Expand All@@ -306,89 +297,6 @@ void Thread::Construct()
ASSERT(m_interruptedContext == NULL);
}

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void Thread::FreeSignalAlternateStack()
{
void *altstack = m_alternateStack;
m_alternateStack = nullptr;

if (altstack != nullptr)
{
stack_t ss, oss;
// The man page for sigaltstack says that when the ss.ss_flags is set to SS_DISABLE,
// all other ss fields are ignored. However, MUSL implementation checks that the
// ss_size is >= MINSIGSTKSZ even in this case.
ss.ss_size = MINSIGSTKSZ;
ss.ss_flags = SS_DISABLE;
ss.ss_sp = NULL;
int st = sigaltstack(&ss, &oss);
if ((st == 0) && (oss.ss_flags != SS_DISABLE))
{
// Make sure this altstack is this PAL's before freeing.
if (oss.ss_sp == altstack)
{
int st = munmap(oss.ss_sp, oss.ss_size);
_ASSERTE(st == 0);
}
}
}
}

bool Thread::EnsureSignalAlternateStack()
{
int st = 0;

stack_t oss;

// Query the current alternate signal stack
st = sigaltstack(NULL, &oss);
if ((st == 0) && (oss.ss_flags == SS_DISABLE))
{
// There is no alternate stack for SIGSEGV handling installed yet so allocate one

// We include the size of the SignalHandlerWorkerReturnPoint in the alternate stack size since the
// context contained in it is large and the SIGSTKSZ was not sufficient on ARM64 during testing.
int altStackSize = SIGSTKSZ;
#ifdef HAS_ADDRESS_SANITIZER
// Asan also uses alternate stack so we increase its size on the SIGSTKSZ * 4 that enough for asan
// (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc)
altStackSize += SIGSTKSZ * 4;
#endif
altStackSize = ALIGN_UP(altStackSize, PalOsPageSize());
int flags = MAP_ANONYMOUS | MAP_PRIVATE;
#ifdef MAP_STACK
flags |= MAP_STACK;
#endif
void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, flags, -1, 0);
if (altStack != MAP_FAILED)
{
// create a guard page for the alternate stack
st = mprotect(altStack, PalOsPageSize(), PROT_NONE);
if (st == 0)
{
stack_t ss;
ss.ss_sp = (char*)altStack;
ss.ss_size = altStackSize;
ss.ss_flags = 0;
st = sigaltstack(&ss, NULL);
}

if (st == 0)
{
m_alternateStack = altStack;
}
else
{
int st2 = munmap(altStack, altStackSize);
_ASSERTE(st2 == 0);
}
}
}

return (st == 0);
}
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

bool Thread::IsInitialized()
{
return (m_ThreadStateFlags != TSF_Unknown);
Expand DownExpand Up@@ -453,10 +361,6 @@ void Thread::Destroy()
}
#endif //FEATURE_SUSPEND_REDIRECTION

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

ASSERT(m_pGCFrameRegistrations == NULL);
}

Expand DownExpand Up@@ -962,19 +866,19 @@ void Thread::Unhijack()
}

// This unhijack routine is called to undo a hijack, that is potentially on a different thread.
//
//
// Although there are many code sequences (here and in asm) to
// perform an unhijack operation, they will never execute concurrently:
//
//
// - A thread may unhijack itself at any time so long as it does that from unmanaged code while in coop mode.
// This ensures that coop thread can access its stack synchronously.
// Unhijacking from unmanaged code ensures that another thread will not attempt to hijack it,
// since we only hijack threads that are executing managed code.
//
//
// - A GC thread may access a thread asynchronously, including unhijacking it.
// Asynchronously accessed thread must be in preemptive mode and should not
// access the managed portion of its stack.
//
//
// - A thread that owns the suspension can access another thread as long as the other thread is
// in preemptive mode or suspended in managed code.
// Either way the other thread cannot be accessing its hijack.
Expand Down
12 changes: 2 additions & 10 deletions src/coreclr/nativeaot/Runtime/thread.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ struct ThreadBuffer
HANDLE m_hPalThread; // WARNING: this may legitimately be INVALID_HANDLE_VALUE
void ** m_ppvHijackedReturnAddressLocation;
void * m_pvHijackedReturnAddress;
uintptr_t m_uHijackedReturnValueFlags;
uintptr_t m_uHijackedReturnValueFlags;
PTR_ExInfo m_pExInfoStackHead;
Object* m_threadAbortException; // ThreadAbortException instance -set only during thread abort
Object* m_pThreadLocalStatics;
Expand All@@ -112,9 +112,6 @@ struct ThreadBuffer
#ifdef FEATURE_GC_STRESS
uint32_t m_uRand; // current per-thread random number
#endif // FEATURE_GC_STRESS
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void * m_alternateStack; // ptr to alternate signal stack
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

struct ReversePInvokeFrame
Expand DownExpand Up@@ -155,7 +152,7 @@ class Thread : private ThreadBuffer
// For suspension APCs it is mostly harmless, but wasteful and in extreme
// cases may force the target thread into stack oveflow.
// We use this flag to avoid sending another APC when one is still going through.
//
//
// On Unix this is an optimization to not queue up more signals when one is
// still being processed.
};
Expand DownExpand Up@@ -315,11 +312,6 @@ class Thread : private ThreadBuffer

bool IsActivationPending();
void SetActivationPending(bool isPending);

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
bool EnsureSignalAlternateStack();
void FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

#ifndef __GCENV_BASE_INCLUDED__
Expand Down
43 changes: 14 additions & 29 deletions src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,9 +11,6 @@
#include "HardwareExceptions.h"
#include "UnixSignals.h"
#include "PalCreateDump.h"
#include "thread.h"
#include "threadstore.h"
#include <sys/mman.h>

#if defined(HOST_APPLE)
#include <mach/mach.h>
Expand DownExpand Up@@ -548,17 +545,6 @@ bool HardwareExceptionHandler(int code, siginfo_t *siginfo, void *context, void*
// Handler for the SIGSEGV signal
void SIGSEGVHandler(int code, siginfo_t *siginfo, void *context)
{
// First check if we have a stack overflow
size_t sp = ((UNIX_CONTEXT *)context)->GetSp();
size_t failureAddress = (size_t)siginfo->si_addr;

// If the failure address is at most one page above or below the stack pointer,
// we have a stack overflow.
if ((failureAddress - (sp - PalOsPageSize())) < (size_t)PalOsPageSize() * 2)
{
PalPrintFatalError("\nProcess is terminating due to StackOverflowException.\n");
RhFailFast();
}
bool isHandled = HardwareExceptionHandler(code, siginfo, context, siginfo->si_addr);
if (isHandled)
{
Expand DownExpand Up@@ -603,8 +589,7 @@ void SIGFPEHandler(int code, siginfo_t *siginfo, void *context)
// Initialize hardware exception handling
bool InitializeHardwareExceptionHandling()
{
// Run SIGSEGV handler on separate stack so we can handle stack overflow. Otherwise, the current (invalid) stack is used and another segfault is raised.
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV, SA_ONSTACK))
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV))
{
return false;
}
Expand All@@ -616,23 +601,23 @@ bool InitializeHardwareExceptionHandling()

#if defined(HOST_APPLE)
#ifndef HOST_TVOS // task_set_exception_ports is not supported on tvOS
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// checks in NativeAOT; continuing execution after LLDB traps an
// EXC_BAD_ACCESS will result in LLDB's EXC_BAD_ACCESS handler being
// invoked again. This also interferes with the translation of SIGFPEs
// to .NET-level ArithmeticExceptions. Work around this here by
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
ASSERT(kr == KERN_SUCCESS);
#endif
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/nativeaot/Runtime/unix/UnixSignals.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,11 +9,11 @@
#include "UnixSignals.h"

// Add handler for hardware exception signal
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags)
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction)
{
struct sigaction newAction;

newAction.sa_flags = SA_RESTART | additionalFlags;
newAction.sa_flags = SA_RESTART;
newAction.sa_handler = NULL;
newAction.sa_sigaction = handler;
newAction.sa_flags |= SA_SIGINFO;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/unix/UnixSignals.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,7 +14,7 @@

typedef void (*SignalHandler)(int code, siginfo_t* siginfo, void* context);

bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags = 0);
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction);
void RestoreSignalHandler(int signal_id, struct sigaction* previousAction);

#endif // __UNIX_SIGNALS_H__
2 changes: 1 addition & 1 deletion src/tests/Common/CoreCLRTestLibrary/Utilities.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ public static bool IsWindowsIoTCore

public static bool IsMonoRuntime => Type.GetType("Mono.RuntimeStructs") != null;
public static bool IsNotMonoRuntime => !IsMonoRuntime;
public static bool IsNativeAot => IsSingleFile && IsNotMonoRuntime && !IsReflectionEmitSupported;
public static bool IsNativeAot => IsNotMonoRuntime && !IsReflectionEmitSupported;

public static bool HasAssemblyFiles => !string.IsNullOrEmpty(typeof(Utilities).Assembly.Location);
public static bool IsSingleFile => !HasAssemblyFiles;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,8 +65,7 @@ struct LargeStruct65536
LargeStruct4096 se;
LargeStruct4096 sf;
}

internal class StackOverflow
class Program
{
[MethodImpl(MethodImplOptions.NoInlining)]
static void InfiniteRecursionA()
Expand DownExpand Up@@ -135,7 +134,7 @@ static void SecondaryThreadsTest(bool smallframe)
}
}

internal static void Run(string[] args)
static void Main(string[] args)
{
bool smallframe = (args[0] == "smallframe");
if (args[1] == "secondary")
Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>
<CLRTestKind>BuildOnly</CLRTestKind>

<Optimize>false</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow.cs" />
</ItemGroup>
</Project>

Original file line numberDiff line numberDiff line change
Expand Up@@ -2,16 +2,16 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;

namespace TestStackOverflow
namespace TestStackOverflow3
{
internal class StackOverflow3
class Program
{
private const int MAX_RECURSIVE_CALLS = 1000000;
static int ctr = 0;

public static void Run()
public static void Main()
{
StackOverflow3 ex = new StackOverflow3();
Program ex = new Program();
ex.Execute();
}

Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>

<Optimize>false</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLRTestKind>BuildOnly</CLRTestKind>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow3.cs" />
</ItemGroup>
</Project>

Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/coreclr/nativeaot/Runtime/inc/CommonTypes.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,6 @@
#ifndef __COMMON_TYPES_H__
#define __COMMON_TYPES_H__

#include <assert.h>
#include <cstddef>
#include <cstdint>
#include <stdlib.h>
Expand Down
104 changes: 4 additions & 100 deletions src/coreclr/nativeaot/Runtime/thread.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,6 @@
#include "CommonTypes.h"
#include "CommonMacros.h"
#include "daccess.h"
#include "CommonMacros.inl"
#include "PalRedhawkCommon.h"
#include "PalRedhawk.h"
#include "rhassert.h"
Expand All@@ -28,11 +27,6 @@
#include "RhConfig.h"
#include "RhVolatile.h"

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
#include <signal.h>
#include <sys/mman.h>
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

#ifndef DACCESS_COMPILE

EXTERN_C NATIVEAOT_API void* REDHAWK_CALLCONV RhpHandleAlloc(void* pObject, int type);
Expand DownExpand Up@@ -287,9 +281,6 @@ void Thread::Construct()
if (StressLog::StressLogOn(~0u, 0))
m_pThreadStressLog = StressLog::CreateThreadStressLog(this);
#endif // STRESS_LOG
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
EnsureSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

// Everything else should be initialized to 0 via the static initialization of tls_CurrentThread.

Expand All@@ -306,89 +297,6 @@ void Thread::Construct()
ASSERT(m_interruptedContext == NULL);
}

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void Thread::FreeSignalAlternateStack()
{
void *altstack = m_alternateStack;
m_alternateStack = nullptr;

if (altstack != nullptr)
{
stack_t ss, oss;
// The man page for sigaltstack says that when the ss.ss_flags is set to SS_DISABLE,
// all other ss fields are ignored. However, MUSL implementation checks that the
// ss_size is >= MINSIGSTKSZ even in this case.
ss.ss_size = MINSIGSTKSZ;
ss.ss_flags = SS_DISABLE;
ss.ss_sp = NULL;
int st = sigaltstack(&ss, &oss);
if ((st == 0) && (oss.ss_flags != SS_DISABLE))
{
// Make sure this altstack is this PAL's before freeing.
if (oss.ss_sp == altstack)
{
int st = munmap(oss.ss_sp, oss.ss_size);
_ASSERTE(st == 0);
}
}
}
}

bool Thread::EnsureSignalAlternateStack()
{
int st = 0;

stack_t oss;

// Query the current alternate signal stack
st = sigaltstack(NULL, &oss);
if ((st == 0) && (oss.ss_flags == SS_DISABLE))
{
// There is no alternate stack for SIGSEGV handling installed yet so allocate one

// We include the size of the SignalHandlerWorkerReturnPoint in the alternate stack size since the
// context contained in it is large and the SIGSTKSZ was not sufficient on ARM64 during testing.
int altStackSize = SIGSTKSZ;
#ifdef HAS_ADDRESS_SANITIZER
// Asan also uses alternate stack so we increase its size on the SIGSTKSZ * 4 that enough for asan
// (see kAltStackSize in compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc)
altStackSize += SIGSTKSZ * 4;
#endif
altStackSize = ALIGN_UP(altStackSize, PalOsPageSize());
int flags = MAP_ANONYMOUS | MAP_PRIVATE;
#ifdef MAP_STACK
flags |= MAP_STACK;
#endif
void* altStack = mmap(NULL, altStackSize, PROT_READ | PROT_WRITE, flags, -1, 0);
if (altStack != MAP_FAILED)
{
// create a guard page for the alternate stack
st = mprotect(altStack, PalOsPageSize(), PROT_NONE);
if (st == 0)
{
stack_t ss;
ss.ss_sp = (char*)altStack;
ss.ss_size = altStackSize;
ss.ss_flags = 0;
st = sigaltstack(&ss, NULL);
}

if (st == 0)
{
m_alternateStack = altStack;
}
else
{
int st2 = munmap(altStack, altStackSize);
_ASSERTE(st2 == 0);
}
}
}

return (st == 0);
}
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

bool Thread::IsInitialized()
{
return (m_ThreadStateFlags != TSF_Unknown);
Expand DownExpand Up@@ -453,10 +361,6 @@ void Thread::Destroy()
}
#endif //FEATURE_SUSPEND_REDIRECTION

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)

ASSERT(m_pGCFrameRegistrations == NULL);
}

Expand DownExpand Up@@ -962,19 +866,19 @@ void Thread::Unhijack()
}

// This unhijack routine is called to undo a hijack, that is potentially on a different thread.
//
//
// Although there are many code sequences (here and in asm) to
// perform an unhijack operation, they will never execute concurrently:
//
//
// - A thread may unhijack itself at any time so long as it does that from unmanaged code while in coop mode.
// This ensures that coop thread can access its stack synchronously.
// Unhijacking from unmanaged code ensures that another thread will not attempt to hijack it,
// since we only hijack threads that are executing managed code.
//
//
// - A GC thread may access a thread asynchronously, including unhijacking it.
// Asynchronously accessed thread must be in preemptive mode and should not
// access the managed portion of its stack.
//
//
// - A thread that owns the suspension can access another thread as long as the other thread is
// in preemptive mode or suspended in managed code.
// Either way the other thread cannot be accessing its hijack.
Expand Down
12 changes: 2 additions & 10 deletions src/coreclr/nativeaot/Runtime/thread.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ struct ThreadBuffer
HANDLE m_hPalThread; // WARNING: this may legitimately be INVALID_HANDLE_VALUE
void ** m_ppvHijackedReturnAddressLocation;
void * m_pvHijackedReturnAddress;
uintptr_t m_uHijackedReturnValueFlags;
uintptr_t m_uHijackedReturnValueFlags;
PTR_ExInfo m_pExInfoStackHead;
Object* m_threadAbortException; // ThreadAbortException instance -set only during thread abort
Object* m_pThreadLocalStatics;
Expand All@@ -112,9 +112,6 @@ struct ThreadBuffer
#ifdef FEATURE_GC_STRESS
uint32_t m_uRand; // current per-thread random number
#endif // FEATURE_GC_STRESS
#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
void * m_alternateStack; // ptr to alternate signal stack
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

struct ReversePInvokeFrame
Expand DownExpand Up@@ -155,7 +152,7 @@ class Thread : private ThreadBuffer
// For suspension APCs it is mostly harmless, but wasteful and in extreme
// cases may force the target thread into stack oveflow.
// We use this flag to avoid sending another APC when one is still going through.
//
//
// On Unix this is an optimization to not queue up more signals when one is
// still being processed.
};
Expand DownExpand Up@@ -315,11 +312,6 @@ class Thread : private ThreadBuffer

bool IsActivationPending();
void SetActivationPending(bool isPending);

#if defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
bool EnsureSignalAlternateStack();
void FreeSignalAlternateStack();
#endif // defined(TARGET_UNIX) && !HAVE_MACH_EXCEPTIONS && !defined(HOST_TVOS)
};

#ifndef __GCENV_BASE_INCLUDED__
Expand Down
43 changes: 14 additions & 29 deletions src/coreclr/nativeaot/Runtime/unix/HardwareExceptions.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,9 +11,6 @@
#include "HardwareExceptions.h"
#include "UnixSignals.h"
#include "PalCreateDump.h"
#include "thread.h"
#include "threadstore.h"
#include <sys/mman.h>

#if defined(HOST_APPLE)
#include <mach/mach.h>
Expand DownExpand Up@@ -548,17 +545,6 @@ bool HardwareExceptionHandler(int code, siginfo_t *siginfo, void *context, void*
// Handler for the SIGSEGV signal
void SIGSEGVHandler(int code, siginfo_t *siginfo, void *context)
{
// First check if we have a stack overflow
size_t sp = ((UNIX_CONTEXT *)context)->GetSp();
size_t failureAddress = (size_t)siginfo->si_addr;

// If the failure address is at most one page above or below the stack pointer,
// we have a stack overflow.
if ((failureAddress - (sp - PalOsPageSize())) < (size_t)PalOsPageSize() * 2)
{
PalPrintFatalError("\nProcess is terminating due to StackOverflowException.\n");
RhFailFast();
}
bool isHandled = HardwareExceptionHandler(code, siginfo, context, siginfo->si_addr);
if (isHandled)
{
Expand DownExpand Up@@ -603,8 +589,7 @@ void SIGFPEHandler(int code, siginfo_t *siginfo, void *context)
// Initialize hardware exception handling
bool InitializeHardwareExceptionHandling()
{
// Run SIGSEGV handler on separate stack so we can handle stack overflow. Otherwise, the current (invalid) stack is used and another segfault is raised.
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV, SA_ONSTACK))
if (!AddSignalHandler(SIGSEGV, SIGSEGVHandler, &g_previousSIGSEGV))
{
return false;
}
Expand All@@ -616,23 +601,23 @@ bool InitializeHardwareExceptionHandling()

#if defined(HOST_APPLE)
#ifndef HOST_TVOS // task_set_exception_ports is not supported on tvOS
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// LLDB installs task-wide Mach exception handlers. XNU dispatches Mach
// exceptions first to any registered "activation" handler and then to
// any registered task handler before dispatching the exception to a
// host-wide Mach exception handler that does translation to POSIX
// signals. This makes it impossible to use LLDB with implicit null
// checks in NativeAOT; continuing execution after LLDB traps an
// EXC_BAD_ACCESS will result in LLDB's EXC_BAD_ACCESS handler being
// invoked again. This also interferes with the translation of SIGFPEs
// to .NET-level ArithmeticExceptions. Work around this here by
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
// installing a no-op task-wide Mach exception handler for
// EXC_BAD_ACCESS and EXC_ARITHMETIC.
kern_return_t kr = task_set_exception_ports(
mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC, /* SIGSEGV, SIGFPE */
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
ASSERT(kr == KERN_SUCCESS);
#endif
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/nativeaot/Runtime/unix/UnixSignals.cpp
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,11 +9,11 @@
#include "UnixSignals.h"

// Add handler for hardware exception signal
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags)
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction)
{
struct sigaction newAction;

newAction.sa_flags = SA_RESTART | additionalFlags;
newAction.sa_flags = SA_RESTART;
newAction.sa_handler = NULL;
newAction.sa_sigaction = handler;
newAction.sa_flags |= SA_SIGINFO;
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/unix/UnixSignals.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,7 +14,7 @@

typedef void (*SignalHandler)(int code, siginfo_t* siginfo, void* context);

bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction, int additionalFlags = 0);
bool AddSignalHandler(int signal, SignalHandler handler, struct sigaction* previousAction);
void RestoreSignalHandler(int signal_id, struct sigaction* previousAction);

#endif // __UNIX_SIGNALS_H__
2 changes: 1 addition & 1 deletion src/tests/Common/CoreCLRTestLibrary/Utilities.cs
Original file line numberDiff line numberDiff line change
Expand Up@@ -94,7 +94,7 @@ public static bool IsWindowsIoTCore

public static bool IsMonoRuntime => Type.GetType("Mono.RuntimeStructs") != null;
public static bool IsNotMonoRuntime => !IsMonoRuntime;
public static bool IsNativeAot => IsSingleFile && IsNotMonoRuntime && !IsReflectionEmitSupported;
public static bool IsNativeAot => IsNotMonoRuntime && !IsReflectionEmitSupported;

public static bool HasAssemblyFiles => !string.IsNullOrEmpty(typeof(Utilities).Assembly.Location);
public static bool IsSingleFile => !HasAssemblyFiles;
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -65,8 +65,7 @@ struct LargeStruct65536
LargeStruct4096 se;
LargeStruct4096 sf;
}

internal class StackOverflow
class Program
{
[MethodImpl(MethodImplOptions.NoInlining)]
static void InfiniteRecursionA()
Expand DownExpand Up@@ -135,7 +134,7 @@ static void SecondaryThreadsTest(bool smallframe)
}
}

internal static void Run(string[] args)
static void Main(string[] args)
{
bool smallframe = (args[0] == "smallframe");
if (args[1] == "secondary")
Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>
<CLRTestKind>BuildOnly</CLRTestKind>

<Optimize>false</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow.cs" />
</ItemGroup>
</Project>

Original file line numberDiff line numberDiff line change
Expand Up@@ -2,16 +2,16 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;

namespace TestStackOverflow
namespace TestStackOverflow3
{
internal class StackOverflow3
class Program
{
private const int MAX_RECURSIVE_CALLS = 1000000;
static int ctr = 0;

public static void Run()
public static void Main()
{
StackOverflow3 ex = new StackOverflow3();
Program ex = new Program();
ex.Execute();
}

Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Uses explicit Main for testing various runtime crashing scenarios. -->
<RequiresProcessIsolation>true</RequiresProcessIsolation>
<ReferenceXUnitWrapperGenerator>false</ReferenceXUnitWrapperGenerator>

<Optimize>false</Optimize>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CLRTestKind>BuildOnly</CLRTestKind>
</PropertyGroup>
<ItemGroup>
<Compile Include="stackoverflow3.cs" />
</ItemGroup>
</Project>

Loading