diff options
-rw-r--r-- | src/ToolBox/SOS/lldbplugin/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/ToolBox/SOS/lldbplugin/coreruncommand.cpp | 48 | ||||
-rw-r--r-- | src/ToolBox/SOS/lldbplugin/sosplugin.cpp | 4 | ||||
-rw-r--r-- | src/ToolBox/SOS/lldbplugin/sosplugin.h | 5 | ||||
-rw-r--r-- | src/coreclr/hosts/unixcorerun/corerun.cpp | 9 | ||||
-rw-r--r-- | src/pal/src/exception/seh.cpp | 19 | ||||
-rw-r--r-- | src/pal/src/exception/signal.cpp | 449 | ||||
-rw-r--r-- | src/pal/src/exception/signal.hpp | 6 | ||||
-rw-r--r-- | src/pal/src/include/pal/seh.hpp | 4 | ||||
-rw-r--r-- | src/pal/src/init/pal.cpp | 4 | ||||
-rw-r--r-- | src/pal/src/thread/threadsusp.cpp | 82 | ||||
-rw-r--r-- | src/vm/corhost.cpp | 4 | ||||
-rw-r--r-- | src/vm/exceptionhandling.cpp | 20 |
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"); } |