diff --git a/src/coreclr/pal/src/exception/seh.cpp b/src/coreclr/pal/src/exception/seh.cpp index 2045084a5683e8..f359b9d2e6646d 100644 --- a/src/coreclr/pal/src/exception/seh.cpp +++ b/src/coreclr/pal/src/exception/seh.cpp @@ -109,7 +109,7 @@ SEHCleanup() { TRACE("Cleaning up SEH\n"); - SEHCleanupSignals(); + SEHCleanupSignals(false /* isChildProcess */); } /*++ diff --git a/src/coreclr/pal/src/exception/signal.cpp b/src/coreclr/pal/src/exception/signal.cpp index c3bdcc793eb95d..4019242d8c5482 100644 --- a/src/coreclr/pal/src/exception/signal.cpp +++ b/src/coreclr/pal/src/exception/signal.cpp @@ -254,8 +254,7 @@ Function : Restore default signal handlers Parameters : - None - + isChildProcess - indicates that it is called from a child process fork (no return value) note : @@ -263,7 +262,7 @@ reason for this function is that during PAL_Terminate, we reach a point where SEH isn't possible anymore (handle manager is off, etc). Past that point, we can't avoid crashing on a signal. --*/ -void SEHCleanupSignals() +void SEHCleanupSignals(bool isChildProcess) { TRACE("Restoring default signal handlers\n"); @@ -276,7 +275,16 @@ void SEHCleanupSignals() restore_signal(SIGFPE, &g_previous_sigfpe); restore_signal(SIGBUS, &g_previous_sigbus); restore_signal(SIGABRT, &g_previous_sigabrt); - restore_signal(SIGSEGV, &g_previous_sigsegv); +#if !HAVE_MACH_EXCEPTIONS + // Do not restore the sigsegv when stack overflow was hit on a thread, + // since all other sigsegvs have to wait in the handler until the process + // dies. + // If it is called by a forked child though, restore the sigsegv unconditionally + if (isChildProcess || (g_stackOverflowHandlerStack != 0)) +#endif + { + restore_signal(SIGSEGV, &g_previous_sigsegv); + } restore_signal(SIGINT, &g_previous_sigint); restore_signal(SIGQUIT, &g_previous_sigquit); } diff --git a/src/coreclr/pal/src/include/pal/signal.hpp b/src/coreclr/pal/src/include/pal/signal.hpp index 6a3e41b4de473f..2dcad31cc44ebf 100644 --- a/src/coreclr/pal/src/include/pal/signal.hpp +++ b/src/coreclr/pal/src/include/pal/signal.hpp @@ -112,9 +112,11 @@ Function : SEHCleanupSignals Restore default signal handlers +Parameters : + isChildProcess - indicates that it is called from a child process fork - (no parameters, no return value) + (no return value) --*/ -void SEHCleanupSignals(); +void SEHCleanupSignals(bool isChildProcess); #endif /* _PAL_SIGNAL_HPP_ */ diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index dcfc4c936f5149..8388bef100fd4e 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -2229,7 +2229,7 @@ PROCCreateCrashDump( if (g_createdumpCallback != nullptr) { // Remove the signal handlers inherited from the runtime process - SEHCleanupSignals(); + SEHCleanupSignals(true /* isChildProcess */); // Call the statically linked createdump code g_createdumpCallback(argv.size(), argv.data()); @@ -2524,7 +2524,7 @@ PROCAbort(int signal, siginfo_t* siginfo) // Restore all signals; the SIGABORT handler to prevent recursion and // the others to prevent multiple core dumps from being generated. - SEHCleanupSignals(); + SEHCleanupSignals(false /* isChildProcess */); // Abort the process after waiting for the core dump to complete abort(); diff --git a/src/tests/baseservices/exceptions/stackoverflow/stackoverflowtester.cs b/src/tests/baseservices/exceptions/stackoverflow/stackoverflowtester.cs index 52707b0508f5ec..f85b67aa9d910e 100644 --- a/src/tests/baseservices/exceptions/stackoverflow/stackoverflowtester.cs +++ b/src/tests/baseservices/exceptions/stackoverflow/stackoverflowtester.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Runtime.InteropServices; using System.Text; namespace TestStackOverflow @@ -24,12 +25,26 @@ static bool TestStackOverflow(string testName, string testArgs, out List testProcess.StartInfo.Arguments = $"{Path.Combine(s_currentPath, "..", testName, $"{testName}.dll")} {testArgs}"; testProcess.StartInfo.UseShellExecute = false; testProcess.StartInfo.RedirectStandardError = true; + testProcess.StartInfo.Environment.Add("DOTNET_DbgEnableMiniDump", "0"); + bool endOfStackTrace = false; testProcess.ErrorDataReceived += (sender, line) => { Console.WriteLine($"\"{line.Data}\""); - if (!string.IsNullOrEmpty(line.Data)) + if (!endOfStackTrace && !string.IsNullOrEmpty(line.Data)) { - lines.Add(line.Data); + // Store lines only till the end of the stack trace. + // In the CI it can also contain lines with createdump info. + if (line.Data.StartsWith("Stack overflow.") || + line.Data.StartsWith("Repeat ") || + line.Data.StartsWith("------") || + line.Data.StartsWith(" at ")) + { + lines.Add(line.Data); + } + else + { + endOfStackTrace = true; + } } }; @@ -256,24 +271,28 @@ static int Main() return 101; } - if (!TestStackOverflowLargeFrameMainThread()) - { - return 102; - } - if (!TestStackOverflowSmallFrameSecondaryThread()) { return 103; } - if (!TestStackOverflowLargeFrameSecondaryThread()) + if ((RuntimeInformation.ProcessArchitecture != Architecture.Arm64) || + ((Environment.OSVersion.Platform != PlatformID.Unix) && (Environment.OSVersion.Platform != PlatformID.MacOSX))) { - return 104; - } + if (!TestStackOverflowLargeFrameMainThread()) + { + return 102; + } - if (!TestStackOverflow3()) - { - return 105; + if (!TestStackOverflowLargeFrameSecondaryThread()) + { + return 104; + } + + if (!TestStackOverflow3()) + { + return 105; + } } return 100; diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 53e2109bec9192..daea1a54bf3fbd 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -86,9 +86,6 @@ - - https://github.com/dotnet/runtime/issues/46175 - https://github.com/dotnet/runtime/issues/80666