summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ToolBox/SOS/lldbplugin/CMakeLists.txt2
-rw-r--r--src/ToolBox/SOS/lldbplugin/coreruncommand.cpp48
-rw-r--r--src/ToolBox/SOS/lldbplugin/sosplugin.cpp4
-rw-r--r--src/ToolBox/SOS/lldbplugin/sosplugin.h5
-rw-r--r--src/coreclr/hosts/unixcorerun/corerun.cpp9
-rw-r--r--src/pal/src/exception/seh.cpp19
-rw-r--r--src/pal/src/exception/signal.cpp449
-rw-r--r--src/pal/src/exception/signal.hpp6
-rw-r--r--src/pal/src/include/pal/seh.hpp4
-rw-r--r--src/pal/src/init/pal.cpp4
-rw-r--r--src/pal/src/thread/threadsusp.cpp82
-rw-r--r--src/vm/corhost.cpp4
-rw-r--r--src/vm/exceptionhandling.cpp20
13 files changed, 281 insertions, 375 deletions
diff --git a/src/ToolBox/SOS/lldbplugin/CMakeLists.txt b/src/ToolBox/SOS/lldbplugin/CMakeLists.txt
index 6448bc6734..ee781a4d2e 100644
--- a/src/ToolBox/SOS/lldbplugin/CMakeLists.txt
+++ b/src/ToolBox/SOS/lldbplugin/CMakeLists.txt
@@ -59,7 +59,9 @@ include_directories(${CLR_DIR}/src/inc)
set(SOURCES
sosplugin.cpp
soscommand.cpp
+ coreruncommand.cpp
debugclient.cpp
+ ${CLR_DIR}/src/coreclr/hosts/unixcorerun/corerun.cpp
)
add_library(sosplugin SHARED ${SOURCES})
diff --git a/src/ToolBox/SOS/lldbplugin/coreruncommand.cpp b/src/ToolBox/SOS/lldbplugin/coreruncommand.cpp
new file mode 100644
index 0000000000..a047488a0b
--- /dev/null
+++ b/src/ToolBox/SOS/lldbplugin/coreruncommand.cpp
@@ -0,0 +1,48 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+#include "sosplugin.h"
+#include <dlfcn.h>
+#include <string>
+
+extern int corerun(const int argc, const char* argv[]);
+
+class corerunCommand : public lldb::SBCommandPluginInterface
+{
+public:
+ corerunCommand()
+ {
+ }
+
+ virtual bool
+ DoExecute (lldb::SBDebugger debugger,
+ char** arguments,
+ lldb::SBCommandReturnObject &result)
+ {
+ if (arguments)
+ {
+ int argc = 0;
+ char **argv = arguments;
+ for (const char* arg = *arguments; arg; arg = *(++arguments))
+ {
+ ++argc;
+ }
+ int exitcode = corerun((const int)argc, (const char**)argv);
+ if (exitcode != 0)
+ {
+ result.SetError("corerun failed");
+ }
+ }
+ return result.Succeeded();
+ }
+};
+
+bool
+corerunCommandInitialize(lldb::SBDebugger debugger)
+{
+ lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
+ interpreter.AddCommand("corerun", new corerunCommand(), "run a managed app inside the debugger");
+ return true;
+}
diff --git a/src/ToolBox/SOS/lldbplugin/sosplugin.cpp b/src/ToolBox/SOS/lldbplugin/sosplugin.cpp
index 90a009277b..a6111b6186 100644
--- a/src/ToolBox/SOS/lldbplugin/sosplugin.cpp
+++ b/src/ToolBox/SOS/lldbplugin/sosplugin.cpp
@@ -12,5 +12,7 @@ namespace lldb {
bool
lldb::PluginInitialize (lldb::SBDebugger debugger)
{
- return sosCommandInitialize(debugger);
+ corerunCommandInitialize(debugger);
+ sosCommandInitialize(debugger);
+ return true;
} \ No newline at end of file
diff --git a/src/ToolBox/SOS/lldbplugin/sosplugin.h b/src/ToolBox/SOS/lldbplugin/sosplugin.h
index 993d7227b6..e031660f7f 100644
--- a/src/ToolBox/SOS/lldbplugin/sosplugin.h
+++ b/src/ToolBox/SOS/lldbplugin/sosplugin.h
@@ -11,4 +11,7 @@
typedef HRESULT (*CommandFunc)(PDEBUG_CLIENT client, const char *args);
bool
-sosCommandInitialize(lldb::SBDebugger debugger); \ No newline at end of file
+sosCommandInitialize(lldb::SBDebugger debugger);
+
+bool
+corerunCommandInitialize(lldb::SBDebugger debugger); \ No newline at end of file
diff --git a/src/coreclr/hosts/unixcorerun/corerun.cpp b/src/coreclr/hosts/unixcorerun/corerun.cpp
index 5f7bb6525b..8308e39f6b 100644
--- a/src/coreclr/hosts/unixcorerun/corerun.cpp
+++ b/src/coreclr/hosts/unixcorerun/corerun.cpp
@@ -321,7 +321,7 @@ int ExecuteManagedAssembly(
return -1;
}
- void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW | RTLD_GLOBAL);
+ void* coreclrLib = dlopen(coreClrDllPath.c_str(), RTLD_NOW | RTLD_LOCAL);
if (coreclrLib != nullptr)
{
ExecuteAssemblyFunction executeAssembly = (ExecuteAssemblyFunction)dlsym(coreclrLib, "ExecuteAssembly");
@@ -402,7 +402,7 @@ int ExecuteManagedAssembly(
return exitCode;
}
-int main(const int argc, const char* argv[])
+int corerun(const int argc, const char* argv[])
{
const char* clrFilesPath;
const char* managedAssemblyPath;
@@ -484,3 +484,8 @@ int main(const int argc, const char* argv[])
managedAssemblyArgv);
return exitCode;
}
+
+int main(const int argc, const char* argv[])
+{
+ return corerun(argc, argv);
+}
diff --git a/src/pal/src/exception/seh.cpp b/src/pal/src/exception/seh.cpp
index 4091914603..ab48ccafe2 100644
--- a/src/pal/src/exception/seh.cpp
+++ b/src/pal/src/exception/seh.cpp
@@ -100,12 +100,12 @@ SEHInitialize (CPalThread *pthrCurrent, DWORD flags)
if (!SEHInitializeConsole())
{
ERROR("SEHInitializeConsole failed!\n");
- SEHCleanup(flags);
+ SEHCleanup();
goto SEHInitializeExit;
}
#if !HAVE_MACH_EXCEPTIONS
- SEHInitializeSignals(flags);
+ SEHInitializeSignals();
if (flags & PAL_INITIALIZE_SIGNAL_THREAD)
{
@@ -113,7 +113,7 @@ SEHInitialize (CPalThread *pthrCurrent, DWORD flags)
if (NO_ERROR != palError)
{
ERROR("StartExternalSignalHandlerThread returned %d\n", palError);
- SEHCleanup(flags);
+ SEHCleanup();
goto SEHInitializeExit;
}
}
@@ -131,20 +131,20 @@ Function :
Undo work done by SEHInitialize
Parameters :
- PAL initialize flags
+ None
(no return value)
--*/
VOID
-SEHCleanup(DWORD flags)
+SEHCleanup()
{
TRACE("Cleaning up SEH\n");
#if HAVE_MACH_EXCEPTIONS
SEHCleanupExceptionPort();
#else
- SEHCleanupSignals(flags);
+ SEHCleanupSignals();
#endif
}
@@ -179,9 +179,8 @@ Parameters:
PEXCEPTION_POINTERS pointers
Return value:
- Does not return
+ Returns only if the exception is unhandled
--*/
-PAL_NORETURN
VOID
SEHProcessException(PEXCEPTION_POINTERS pointers)
{
@@ -197,9 +196,7 @@ SEHProcessException(PEXCEPTION_POINTERS pointers)
throw exception;
}
- ASSERT("Unhandled hardware exception %08x\n", pointers->ExceptionRecord->ExceptionCode);
-
- ExitProcess(pointers->ExceptionRecord->ExceptionCode);
+ TRACE("Unhandled hardware exception %08x\n", pointers->ExceptionRecord->ExceptionCode);
}
/*++
diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp
index 8e5f52825c..0496362de1 100644
--- a/src/pal/src/exception/signal.cpp
+++ b/src/pal/src/exception/signal.cpp
@@ -56,43 +56,36 @@ typedef void *siginfo_t;
#endif /* !HAVE_SIGINFO_T */
typedef void (*SIGFUNC)(int, siginfo_t *, void *);
-/* Static variables ***********************************************************/
-static LONG fatal_signal_received;
-
/* internal function declarations *********************************************/
-static void sigint_handler(int code, siginfo_t *siginfo, void *context);
-static void sigquit_handler(int code, siginfo_t *siginfo, void *context);
static void sigill_handler(int code, siginfo_t *siginfo, void *context);
static void sigfpe_handler(int code, siginfo_t *siginfo, void *context);
static void sigsegv_handler(int code, siginfo_t *siginfo, void *context);
static void sigtrap_handler(int code, siginfo_t *siginfo, void *context);
static void sigbus_handler(int code, siginfo_t *siginfo, void *context);
-static void fatal_signal_handler(int code, siginfo_t *siginfo, void *context);
+#if USE_SIGNALS_FOR_THREAD_SUSPENSION
+void CorUnix::suspend_handler(int code, siginfo_t *siginfo, void *context);
+void CorUnix::resume_handler(int code, siginfo_t *siginfo, void *context);
+#endif // USE_SIGNALS_FOR_THREAD_SUSPENSION
+
static void common_signal_handler(PEXCEPTION_POINTERS pointers, int code,
native_context_t *ucontext);
-void handle_signal(int signal_id, SIGFUNC sigfunc);
-inline void check_pal_initialize(int signal_id);
+static void handle_signal(int signal_id, SIGFUNC sigfunc, struct sigaction *previousAction);
+static void restore_signal(int signal_id, struct sigaction *previousAction);
+inline void check_pal_initialize(int signal_id, struct sigaction *previousAction);
-#if HAVE__THREAD_SYS_SIGRETURN
-int _thread_sys_sigreturn(native_context_t *);
-#endif
+/* internal data declarations *********************************************/
-#if USE_SIGNALS_FOR_THREAD_SUSPENSION
-void CorUnix::suspend_handler(int code, siginfo_t *siginfo, void *context)
-{
- check_pal_initialize(code);
- CPalThread *pThread = InternalGetCurrentThread();
- pThread->suspensionInfo.HandleSuspendSignal(pThread);
-}
+struct sigaction g_previous_sigill;
+struct sigaction g_previous_sigtrap;
+struct sigaction g_previous_sigfpe;
+struct sigaction g_previous_sigbus;
+struct sigaction g_previous_sigsegv;
-void CorUnix::resume_handler(int code, siginfo_t *siginfo, void *context)
-{
- check_pal_initialize(code);
- CPalThread *pThread = InternalGetCurrentThread();
- pThread->suspensionInfo.HandleResumeSignal();
-}
+#if USE_SIGNALS_FOR_THREAD_SUSPENSION
+struct sigaction g_previous_sigusr1;
+struct sigaction g_previous_sigusr2;
#endif // USE_SIGNALS_FOR_THREAD_SUSPENSION
/* public function definitions ************************************************/
@@ -104,16 +97,14 @@ Function :
Set-up signal handlers to catch signals and translate them to exceptions
Parameters :
- PAL initialize flags
+ None
(no return value)
--*/
-void SEHInitializeSignals(DWORD flags)
+void SEHInitializeSignals()
{
TRACE("Initializing signal handlers\n");
- fatal_signal_received = 0;
-
/* we call handle signal for every possible signal, even
if we don't provide a signal handler.
@@ -127,54 +118,25 @@ void SEHInitializeSignals(DWORD flags)
see sigaction man page for more details
*/
- handle_signal(SIGILL, sigill_handler);
- handle_signal(SIGTRAP, sigtrap_handler);
- handle_signal(SIGFPE, sigfpe_handler);
- handle_signal(SIGBUS, sigbus_handler);
- handle_signal(SIGSEGV, sigsegv_handler);
+ handle_signal(SIGILL, sigill_handler, &g_previous_sigill);
+ handle_signal(SIGTRAP, sigtrap_handler, &g_previous_sigtrap);
+ handle_signal(SIGFPE, sigfpe_handler, &g_previous_sigfpe);
+ handle_signal(SIGBUS, sigbus_handler, &g_previous_sigbus);
+ handle_signal(SIGSEGV, sigsegv_handler, &g_previous_sigsegv);
#if USE_SIGNALS_FOR_THREAD_SUSPENSION
- handle_signal(SIGUSR1, suspend_handler);
- handle_signal(SIGUSR2, resume_handler);
+ handle_signal(SIGUSR1, suspend_handler, &g_previous_sigusr1);
+ handle_signal(SIGUSR2, resume_handler, &g_previous_sigusr2);
#endif
- if (flags & PAL_INITIALIZE_ALL_SIGNALS)
- {
- handle_signal(SIGHUP, fatal_signal_handler);
- handle_signal(SIGINT, sigint_handler);
- handle_signal(SIGQUIT, sigquit_handler);
- handle_signal(SIGABRT, fatal_signal_handler);
-#ifdef SIGEMT
- handle_signal(SIGEMT, fatal_signal_handler);
-#endif // SIGEMT
- handle_signal(SIGSYS, fatal_signal_handler);
- handle_signal(SIGALRM, fatal_signal_handler);
- handle_signal(SIGTERM, fatal_signal_handler);
- handle_signal(SIGURG, NULL);
- handle_signal(SIGTSTP, NULL);
- handle_signal(SIGCONT, NULL);
- handle_signal(SIGCHLD, NULL);
- handle_signal(SIGTTIN, NULL);
- handle_signal(SIGTTOU, NULL);
- handle_signal(SIGIO, NULL);
- handle_signal(SIGXCPU, fatal_signal_handler);
- handle_signal(SIGXFSZ, fatal_signal_handler);
- handle_signal(SIGVTALRM, fatal_signal_handler);
- handle_signal(SIGPROF, fatal_signal_handler);
- handle_signal(SIGWINCH, NULL);
-#ifdef SIGINFO
- handle_signal(SIGINFO, NULL);
-#endif // SIGINFO
-
- /* The default action for SIGPIPE is process termination.
- Since SIGPIPE can be signaled when trying to write on a socket for which
- the connection has been dropped, we need to tell the system we want
- to ignore this signal.
-
- Instead of terminating the process, the system call which would had
- issued a SIGPIPE will, instead, report an error and set errno to EPIPE.
- */
- signal(SIGPIPE, SIG_IGN);
- }
+ /* The default action for SIGPIPE is process termination.
+ Since SIGPIPE can be signaled when trying to write on a socket for which
+ the connection has been dropped, we need to tell the system we want
+ to ignore this signal.
+
+ Instead of terminating the process, the system call which would had
+ issued a SIGPIPE will, instead, report an error and set errno to EPIPE.
+ */
+ signal(SIGPIPE, SIG_IGN);
}
/*++
@@ -184,7 +146,7 @@ Function :
Restore default signal handlers
Parameters :
- PAL initialize flags
+ None
(no return value)
@@ -193,80 +155,55 @@ 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 (DWORD flags)
+void SEHCleanupSignals()
{
TRACE("Restoring default signal handlers\n");
- handle_signal(SIGILL, NULL);
- handle_signal(SIGTRAP, NULL);
- handle_signal(SIGFPE, NULL);
- handle_signal(SIGBUS, NULL);
- handle_signal(SIGSEGV, NULL);
-
- if (flags & PAL_INITIALIZE_ALL_SIGNALS)
- {
- handle_signal(SIGHUP, NULL);
- handle_signal(SIGINT, NULL);
- handle_signal(SIGQUIT, NULL);
- handle_signal(SIGABRT, NULL);
-#ifdef SIGEMT
- handle_signal(SIGEMT, NULL);
-#endif // SIGEMT
- handle_signal(SIGSYS, NULL);
- handle_signal(SIGALRM, NULL);
- handle_signal(SIGTERM, NULL);
- handle_signal(SIGXCPU, NULL);
- handle_signal(SIGXFSZ, NULL);
- handle_signal(SIGVTALRM, NULL);
- handle_signal(SIGPROF, NULL);
- handle_signal(SIGPIPE, NULL);
- /* Do not remove handlers for SIGUSR1 and SIGUSR2. They must remain so threads can be suspended
+ /* Do not remove handlers for SIGUSR1 and SIGUSR2. They must remain so threads can be suspended
during cleanup after this function has been called. */
- }
+ restore_signal(SIGILL, &g_previous_sigill);
+ restore_signal(SIGTRAP, &g_previous_sigtrap);
+ restore_signal(SIGFPE, &g_previous_sigfpe);
+ restore_signal(SIGBUS, &g_previous_sigbus);
+ restore_signal(SIGSEGV, &g_previous_sigsegv);
}
-
/* internal function definitions **********************************************/
-/*++
-Function :
- sigint_handler
+#if USE_SIGNALS_FOR_THREAD_SUSPENSION
- This signal is now handled by the PAL signal handling thread : see seh.cpp
- The SIGINT signal (CONTROL_C_EXIT exception) is intercepted by the signal handling thread,
- which creates a new thread, that calls SEHHandleControlEvent, to handle the SIGINT.
+void CorUnix::suspend_handler(int code, siginfo_t *siginfo, void *context)
+{
+ check_pal_initialize(code, &g_previous_sigusr1);
-Parameters :
- POSIX signal handler parameter list ("man sigaction" for details)
+ CPalThread *pThread = InternalGetCurrentThread();
+ pThread->suspensionInfo.HandleSuspendSignal(pThread);
- (no return value)
---*/
-static void sigint_handler(int code, siginfo_t *siginfo, void *context)
-{
- check_pal_initialize(code);
- ASSERT("Should not reach sigint_handler\n");
+ TRACE("SIGUSR1 signal was unhandled; chaining to previous sigaction\n");
+
+ if (g_previous_sigusr1.sa_sigaction != NULL)
+ {
+ g_previous_sigusr1.sa_sigaction(code, siginfo, context);
+ }
}
-/*++
-Function :
- sigquit_handler
-
- This signal is now handled by the PAL signal handling thread : see seh.cpp
- The SIGQUIT signal is intercepted by the signal handling thread,
- which create a new thread, that calls SEHHandleControlEvent, to handle the SIGQUIT.
+void CorUnix::resume_handler(int code, siginfo_t *siginfo, void *context)
+{
+ check_pal_initialize(code, &g_previous_sigusr2);
-Parameters :
- POSIX signal handler parameter list ("man sigaction" for details)
+ CPalThread *pThread = InternalGetCurrentThread();
+ pThread->suspensionInfo.HandleResumeSignal();
- (no return value)
---*/
-static void sigquit_handler(int code, siginfo_t *siginfo, void *context)
-{
- check_pal_initialize(code);
- ASSERT("Should not reach sigquit_handler\n");
+ TRACE("SIGUSR2 signal was unhandled; chaining to previous sigaction\n");
+ if (g_previous_sigusr2.sa_sigaction != NULL)
+ {
+ g_previous_sigusr2.sa_sigaction(code, siginfo, context);
+ }
}
+#endif // USE_SIGNALS_FOR_THREAD_SUSPENSION
+
/*++
Function :
sigill_handler
@@ -280,7 +217,8 @@ Parameters :
--*/
static void sigill_handler(int code, siginfo_t *siginfo, void *context)
{
- check_pal_initialize(code);
+ check_pal_initialize(code, &g_previous_sigill);
+
EXCEPTION_RECORD record;
EXCEPTION_POINTERS pointers;
native_context_t *ucontext;
@@ -297,7 +235,12 @@ static void sigill_handler(int code, siginfo_t *siginfo, void *context)
common_signal_handler(&pointers, code, ucontext);
- TRACE("SIGILL Signal was handled; continuing execution.\n");
+ TRACE("SIGILL signal was unhandled; chaining to previous sigaction\n");
+
+ if (g_previous_sigill.sa_sigaction != NULL)
+ {
+ g_previous_sigill.sa_sigaction(code, siginfo, context);
+ }
}
/*++
@@ -313,7 +256,8 @@ Parameters :
--*/
static void sigfpe_handler(int code, siginfo_t *siginfo, void *context)
{
- check_pal_initialize(code);
+ check_pal_initialize(code, &g_previous_sigfpe);
+
EXCEPTION_RECORD record;
EXCEPTION_POINTERS pointers;
native_context_t *ucontext;
@@ -330,7 +274,12 @@ static void sigfpe_handler(int code, siginfo_t *siginfo, void *context)
common_signal_handler(&pointers, code, ucontext);
- TRACE("SIGFPE Signal was handled; continuing execution.\n");
+ TRACE("SIGFPE signal was unhandled; chaining to previous sigaction\n");
+
+ if (g_previous_sigfpe.sa_sigaction != NULL)
+ {
+ g_previous_sigfpe.sa_sigaction(code, siginfo, context);
+ }
}
/*++
@@ -346,7 +295,8 @@ Parameters :
--*/
static void sigsegv_handler(int code, siginfo_t *siginfo, void *context)
{
- check_pal_initialize(code);
+ check_pal_initialize(code, &g_previous_sigsegv);
+
EXCEPTION_RECORD record;
EXCEPTION_POINTERS pointers;
native_context_t *ucontext;
@@ -371,7 +321,12 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context)
common_signal_handler(&pointers, code, ucontext);
- TRACE("SIGSEGV Signal was handled; continuing execution.\n");
+ TRACE("SIGSEGV signal was unhandled; chaining to previous sigaction\n");
+
+ if (g_previous_sigsegv.sa_sigaction != NULL)
+ {
+ g_previous_sigsegv.sa_sigaction(code, siginfo, context);
+ }
}
/*++
@@ -387,7 +342,8 @@ Parameters :
--*/
static void sigtrap_handler(int code, siginfo_t *siginfo, void *context)
{
- check_pal_initialize(code);
+ check_pal_initialize(code, &g_previous_sigtrap);
+
EXCEPTION_RECORD record;
EXCEPTION_POINTERS pointers;
native_context_t *ucontext;
@@ -404,7 +360,12 @@ static void sigtrap_handler(int code, siginfo_t *siginfo, void *context)
common_signal_handler(&pointers, code, ucontext);
- TRACE("SIGTRAP Signal was handled; continuing execution.\n");
+ TRACE("SIGTRAP signal was unhandled; chaining to previous sigaction\n");
+
+ if (g_previous_sigtrap.sa_sigaction != NULL)
+ {
+ g_previous_sigtrap.sa_sigaction(code, siginfo, context);
+ }
}
/*++
@@ -420,7 +381,7 @@ Parameters :
--*/
static void sigbus_handler(int code, siginfo_t *siginfo, void *context)
{
- check_pal_initialize(code);
+ check_pal_initialize(code, &g_previous_sigbus);
EXCEPTION_RECORD record;
EXCEPTION_POINTERS pointers;
native_context_t *ucontext;
@@ -445,7 +406,12 @@ static void sigbus_handler(int code, siginfo_t *siginfo, void *context)
common_signal_handler(&pointers, code, ucontext);
- TRACE("SIGBUS Signal was handled; continuing execution.\n");
+ TRACE("SIGBUS signal was unhandled; chaining to previous sigaction\n");
+
+ if (g_previous_sigbus.sa_sigaction != NULL)
+ {
+ g_previous_sigbus.sa_sigaction(code, siginfo, context);
+ }
}
/*++
@@ -494,25 +460,6 @@ BOOL SEHGetSafeState(CPalThread *pthrCurrent)
/*++
Function :
- fatal_signal_handler
-
- This signal handler has been replaced by the PAL signal handling thread : see seh.cpp
- Any signals assigned to this handler are intercepted by the signal handling thread, which
- initiates process termination and cleanup.
-
-Parameters :
- POSIX signal handler parameter list ("man sigaction" for details)
-
- (no return value)
---*/
-void fatal_signal_handler(int code, siginfo_t *siginfo, void *context)
-{
- check_pal_initialize(code);
- ASSERT("Should not reach fatal_signal_handler\n");
-}
-
-/*++
-Function :
common_signal_handler
common code for all signal handlers
@@ -530,7 +477,6 @@ Note:
static void common_signal_handler(PEXCEPTION_POINTERS pointers, int code,
native_context_t *ucontext)
{
- check_pal_initialize(code);
sigset_t signal_set;
CONTEXT context;
@@ -541,8 +487,7 @@ static void common_signal_handler(PEXCEPTION_POINTERS pointers, int code,
// Fill context record with required information. from pal.h :
// On non-Win32 platforms, the CONTEXT pointer in the
// PEXCEPTION_POINTERS will contain at least the CONTEXT_CONTROL registers.
- CONTEXTFromNativeContext(ucontext, &context,
- CONTEXT_CONTROL | CONTEXT_INTEGER);
+ CONTEXTFromNativeContext(ucontext, &context, CONTEXT_CONTROL | CONTEXT_INTEGER);
pointers->ContextRecord = &context;
@@ -566,40 +511,51 @@ Function :
Parameters :
int signal_id : signal to handle
SIGFUNC sigfunc : signal handler
+ previousAction : previous sigaction struct
(no return value)
note : if sigfunc is NULL, the default signal handler is restored
--*/
-void handle_signal(int signal_id, SIGFUNC sigfunc)
+void handle_signal(int signal_id, SIGFUNC sigfunc, struct sigaction *previousAction)
{
- struct sigaction act;
-
- act.sa_flags = SA_RESTART;
+ struct sigaction newAction;
- if( NULL == sigfunc )
- {
- act.sa_handler=SIG_DFL;
+ newAction.sa_flags = SA_RESTART;
#if HAVE_SIGINFO_T
- act.sa_sigaction=NULL;
-#endif /* HAVE_SIGINFO_T */
- }
- else
- {
-#if HAVE_SIGINFO_T
- act.sa_handler=NULL;
- act.sa_sigaction=sigfunc;
- act.sa_flags |= SA_SIGINFO;
+ newAction.sa_handler = NULL;
+ newAction.sa_sigaction = sigfunc;
+ newAction.sa_flags |= SA_SIGINFO;
#else /* HAVE_SIGINFO_T */
- act.sa_handler = SIG_DFL;
+ newAction.sa_handler = SIG_DFL;
#endif /* HAVE_SIGINFO_T */
+ sigemptyset(&newAction.sa_mask);
+
+ if (-1 == sigaction(signal_id, &newAction, previousAction))
+ {
+ ASSERT("handle_signal: sigaction() call failed with error code %d (%s)\n",
+ errno, strerror(errno));
}
- sigemptyset(&act.sa_mask);
+}
+
+/*++
+Function :
+ restore_signal
- if(-1==sigaction(signal_id,&act,NULL))
+ restore handler for specified signal
+
+Parameters :
+ int signal_id : signal to handle
+ previousAction : previous sigaction struct to restore
+
+ (no return value)
+--*/
+void restore_signal(int signal_id, struct sigaction *previousAction)
+{
+ if (-1 == sigaction(signal_id, previousAction, NULL))
{
- ASSERT("sigaction() call failed with error code %d (%s)\n",
- errno, strerror(errno));
+ ASSERT("restore_signal: sigaction() call failed with error code %d (%s)\n",
+ errno, strerror(errno));
}
}
@@ -612,14 +568,15 @@ Function :
Parameters :
int signal_id : signal to handle
+ previousAction : previous sigaction struct to restore
(no return value)
--*/
-inline void check_pal_initialize(int signal_id)
+inline void check_pal_initialize(int signal_id, struct sigaction *previousAction)
{
if (!PALIsInitialized())
{
- handle_signal(signal_id, NULL);
+ restore_signal(signal_id, previousAction);
kill(gPID, signal_id);
}
}
@@ -640,17 +597,9 @@ ControlHandlerThreadRoutine(
PVOID pvSignal
);
-static
-DWORD
-PALAPI
-ShutdownThreadRoutine(
- PVOID
- );
-
PAL_ERROR
StartExternalSignalHandlerThread(
- CPalThread *pthr
- )
+ CPalThread *pthr)
{
PAL_ERROR palError = NO_ERROR;
@@ -694,7 +643,6 @@ ExternalSignalHandlerThreadRoutine(
{
DWORD dwThreadId;
bool fContinue = TRUE;
- bool fShutdownThreadLaunched = FALSE;
HANDLE hThread;
int iError;
int iSignal;
@@ -716,54 +664,10 @@ ExternalSignalHandlerThreadRoutine(
(void)sigfillset(&sigsetAll);
(void)sigdelset(&sigsetAll, SIGPROF);
- (void)sigfillset(&sigsetWait);
-
-#if SIGWAIT_FAILS_WHEN_PASSED_FULL_SIGSET
- (void)sigdelset(&sigsetWait, SIGKILL);
- (void)sigdelset(&sigsetWait, SIGSTOP);
- (void)sigdelset(&sigsetWait, SIGWAITING);
- (void)sigdelset(&sigsetWait, SIGALRM1);
-#endif
-
- //
- // We don't want this thread to wait for signals that
- // we want to leave to the default handler (primarily
- // those involved with terminal or job control).
- //
- //
-
- (void)sigdelset(&sigsetWait, SIGURG);
- (void)sigdelset(&sigsetWait, SIGTSTP);
- (void)sigdelset(&sigsetWait, SIGCONT);
- (void)sigdelset(&sigsetWait, SIGCHLD);
- (void)sigdelset(&sigsetWait, SIGTTIN);
- (void)sigdelset(&sigsetWait, SIGTTOU);
- (void)sigdelset(&sigsetWait, SIGIO);
- (void)sigdelset(&sigsetWait, SIGWINCH);
-#ifdef SIGINFO
- (void)sigdelset(&sigsetWait, SIGINFO);
-#endif // SIGINFO
- (void)sigdelset(&sigsetWait, SIGPROF);
-
- //
- // Ideally, we'd like externally generated translated signals
- // (i.e., the signals that we convert to exceptions) to be directed
- // to this thread as well. Unfortunately on some platforms the sigwait
- // will take precedence over the synchronous signal on a thread within
- // this process -- the signal will get directed to this thread, instead
- // of the thread that executed the instruction that raised the signal.
- // This, needless to say, is not good for our EH mechanism.
- //
- // Furthermore, since these signals are not masked on other threads
- // on other platforms the externally generated signal will be directed
- // to one of those threads, instead of this one.
- //
- (void)sigdelset(&sigsetWait, SIGILL);
- (void)sigdelset(&sigsetWait, SIGTRAP);
- (void)sigdelset(&sigsetWait, SIGFPE);
- (void)sigdelset(&sigsetWait, SIGBUS);
- (void)sigdelset(&sigsetWait, SIGSEGV);
+ (void)sigemptyset(&sigsetWait);
+ (void)sigaddset(&sigsetWait, SIGINT);
+ (void)sigaddset(&sigsetWait, SIGQUIT);
//
// Mask off all signals for this thread
@@ -850,59 +754,13 @@ ExternalSignalHandlerThreadRoutine(
}
InternalCloseHandle(pthr, hThread);
-
break;
}
default:
- {
- //
- // Any other signal received externally is fatal. If we
- // haven't yet spun up a shutdown thread, do so now; if we
- // have, we want to wait for a bit (in the hope that the
- // shutdown thread is able to complete) and then exit.
- //
-
- if (fShutdownThreadLaunched)
- {
- sleep(c_iShutdownWaitTime);
- fContinue = FALSE;
- break;
- }
-
- //
- // Spin up a new thread to perform a graceful shutdown. As
- // with the console control handlers we want this thread
- // to continue to handle external signals.
- //
- // We're going to call TerminateProcess so it's OK for
- // this thread to be a worker thread -- DllMain routines
- // will not be called.
- //
-
- fShutdownThreadLaunched = TRUE;
-
- palError = InternalCreateThread(
- pthr,
- NULL,
- 0,
- ShutdownThreadRoutine,
- NULL,
- 0,
- PalWorkerThread,
- &dwThreadId,
- &hThread
- );
-
- if (NO_ERROR != palError)
- {
- fContinue = FALSE;
- break;
- }
-
- InternalCloseHandle(pthr, hThread);
+ ASSERT("Unexpect signal %d in signal thread\n", iSignal);
+ fContinue = FALSE;
break;
- }
}
}
@@ -927,15 +785,4 @@ ControlHandlerThreadRoutine(
return 0;
}
-static
-DWORD
-PALAPI
-ShutdownThreadRoutine(
- PVOID
- )
-{
- TerminateProcess(GetCurrentProcess(), CONTROL_C_EXIT);
- return 0;
-}
-
#endif // !HAVE_MACH_EXCEPTIONS
diff --git a/src/pal/src/exception/signal.hpp b/src/pal/src/exception/signal.hpp
index 4940515577..70a5145fc9 100644
--- a/src/pal/src/exception/signal.hpp
+++ b/src/pal/src/exception/signal.hpp
@@ -30,11 +30,11 @@ Function :
Set-up signal handlers to catch signals and translate them to exceptions
Parameters :
- PAL initialize flags
+ None
(no return value)
--*/
-void SEHInitializeSignals(DWORD flags);
+void SEHInitializeSignals();
/*++
Function :
@@ -44,7 +44,7 @@ Function :
(no parameters, no return value)
--*/
-void SEHCleanupSignals(DWORD flags);
+void SEHCleanupSignals();
#if (__GNUC__ > 3 || \
(__GNUC__ == 3 && __GNUC_MINOR__ > 2))
diff --git a/src/pal/src/include/pal/seh.hpp b/src/pal/src/include/pal/seh.hpp
index 399a417ea7..b6bbad06a7 100644
--- a/src/pal/src/include/pal/seh.hpp
+++ b/src/pal/src/include/pal/seh.hpp
@@ -53,12 +53,12 @@ Function :
Clean up SEH-related stuff(signals, etc)
Parameters:
- flags : PAL initialize flags
+ None
(no return value)
--*/
VOID
-SEHCleanup(DWORD flags);
+SEHCleanup();
/*++
Function:
diff --git a/src/pal/src/init/pal.cpp b/src/pal/src/init/pal.cpp
index 7135e0c5c0..0e33e81223 100644
--- a/src/pal/src/init/pal.cpp
+++ b/src/pal/src/init/pal.cpp
@@ -534,7 +534,7 @@ CLEANUP10:
CLEANUP8:
MAPCleanup();
CLEANUP6:
- SEHCleanup(flags);
+ SEHCleanup();
CLEANUP5:
PROCCleanupInitialProcess();
CLEANUP4:
@@ -847,7 +847,7 @@ PALCommonCleanup(PALCLEANUP_STEP step, BOOL full_cleanup)
LOADFreeModules requires SEH to be functional when calling DllMain.
Therefore SEHCleanup must go between LOADFreeModules and
PROCCleanupInitialProcess */
- SEHCleanup(PAL_INITIALIZE_ALL);
+ SEHCleanup();
PROCCleanupInitialProcess();
}
diff --git a/src/pal/src/thread/threadsusp.cpp b/src/pal/src/thread/threadsusp.cpp
index b8bab873e6..d3602b34a2 100644
--- a/src/pal/src/thread/threadsusp.cpp
+++ b/src/pal/src/thread/threadsusp.cpp
@@ -1674,35 +1674,33 @@ CThreadSuspensionInfo::HandleSuspendSignal(
CPalThread *pthrTarget
)
{
- if (!GetSuspendSignalSent())
+ if (GetSuspendSignalSent())
{
- ASSERT("Entered suspend handler (by receiving SIGUSR1) but not due to SuspendThread.\n");
- return;
- }
- SetSuspendSignalSent(FALSE);
-
- if (IsSuspensionStateSafe())
- {
- SetSuspPending(FALSE);
- if (!pthrTarget->GetCreateSuspended())
+ SetSuspendSignalSent(FALSE);
+
+ if (IsSuspensionStateSafe())
{
- /* Note that we don't call sem_post when CreateSuspended is true.
- This is to handle the scenario where a thread suspends itself and
- another thread then attempts to suspend that thread. It won't wait
- on the semaphore if the self suspending thread already posted
- but didn't reach the matching wait. */
- PostOnSuspendSemaphore();
+ SetSuspPending(FALSE);
+ if (!pthrTarget->GetCreateSuspended())
+ {
+ /* Note that we don't call sem_post when CreateSuspended is true.
+ This is to handle the scenario where a thread suspends itself and
+ another thread then attempts to suspend that thread. It won't wait
+ on the semaphore if the self suspending thread already posted
+ but didn't reach the matching wait. */
+ PostOnSuspendSemaphore();
+ }
+ else
+ {
+ pthrTarget->SetStartStatus(TRUE);
+ }
+ sigsuspend(&smSuspmask);
}
- else
+ else
{
- pthrTarget->SetStartStatus(TRUE);
- }
- sigsuspend(&smSuspmask);
+ SetSuspPending(TRUE);
+ }
}
- else
- {
- SetSuspPending(TRUE);
- }
}
/*++
@@ -1720,27 +1718,25 @@ continue execution.
void
CThreadSuspensionInfo::HandleResumeSignal()
{
- if (!GetResumeSignalSent())
- {
- ASSERT("Entered resume handler (by receiving SIGUSR2) but not due to ResumeThread.\n");
- return;
- }
- SetResumeSignalSent(FALSE);
-
- if (GetSuspCount() != 0)
- {
- ASSERT("Should not be resuming a thread whose suspension count is %d.\n", GetSuspCount());
- return;
- }
-
- // This thread is no longer suspended - if it self suspended,
- // then its self suspension field should now be set to FALSE.
- if (GetSelfSusp())
+ if (GetResumeSignalSent())
{
- SetSelfSusp(FALSE);
+ SetResumeSignalSent(FALSE);
+
+ if (GetSuspCount() != 0)
+ {
+ ASSERT("Should not be resuming a thread whose suspension count is %d.\n", GetSuspCount());
+ return;
+ }
+
+ // This thread is no longer suspended - if it self suspended,
+ // then its self suspension field should now be set to FALSE.
+ if (GetSelfSusp())
+ {
+ SetSelfSusp(FALSE);
+ }
+
+ PostOnResumeSemaphore();
}
-
- PostOnResumeSemaphore();
}
#else // USE_SIGNALS_FOR_THREAD_SUSPENSION
diff --git a/src/vm/corhost.cpp b/src/vm/corhost.cpp
index 6e26ceb7d1..c887ceacde 100644
--- a/src/vm/corhost.cpp
+++ b/src/vm/corhost.cpp
@@ -1945,8 +1945,10 @@ HRESULT CorHost2::SetStartupFlags(STARTUP_FLAGS flag)
}
CONTRACTL_END;
- if(g_fEEStarted)
+ if (m_fStarted)
+ {
return HOST_E_INVALIDOPERATION;
+ }
if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_gcServer) != 0)
{
diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp
index 36c081963f..ed5e162e9a 100644
--- a/src/vm/exceptionhandling.cpp
+++ b/src/vm/exceptionhandling.cpp
@@ -4945,6 +4945,10 @@ bool IsDivByZeroAnIntegerOverflow(PCONTEXT pContext)
VOID PALAPI HandleHardwareException(PAL_SEHException* ex)
{
+ if (!g_fEEStarted)
+ {
+ return;
+ }
if (ex->ExceptionRecord.ExceptionCode != STATUS_BREAKPOINT && ex->ExceptionRecord.ExceptionCode != STATUS_SINGLE_STEP)
{
// A hardware exception is handled only if it happened in a jitted code or
@@ -4989,13 +4993,13 @@ VOID PALAPI HandleHardwareException(PAL_SEHException* ex)
UNREACHABLE();
}
}
- else
+ else
{
// This is a breakpoint or single step stop, we report it to the debugger.
- Thread *pThread = GetThread();
+ Thread *pThread = GetThread();
if (pThread != NULL && g_pDebugInterface != NULL)
{
- if (ex->ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT)
+ if (ex->ExceptionRecord.ExceptionCode == STATUS_BREAKPOINT)
{
// If this is breakpoint context, it is set up to point to an instruction after the break instruction.
// But debugger expects to see context that points to the break instruction, that's why we correct it.
@@ -5004,13 +5008,13 @@ VOID PALAPI HandleHardwareException(PAL_SEHException* ex)
}
if (g_pDebugInterface->FirstChanceNativeException(&ex->ExceptionRecord,
- &ex->ContextRecord,
- ex->ExceptionRecord.ExceptionCode,
- pThread))
+ &ex->ContextRecord,
+ ex->ExceptionRecord.ExceptionCode,
+ pThread))
{
RtlRestoreContext(&ex->ContextRecord, &ex->ExceptionRecord);
- }
- else
+ }
+ else
{
_ASSERTE(!"Looks like a random breakpoint/trap that was not prepared by the EE debugger");
}