diff --git a/ddprof-lib/src/main/cpp/os.h b/ddprof-lib/src/main/cpp/os.h index 3b909a0e9..54ba25549 100644 --- a/ddprof-lib/src/main/cpp/os.h +++ b/ddprof-lib/src/main/cpp/os.h @@ -50,7 +50,6 @@ class JitWriteProtection { ~JitWriteProtection(); }; - class OS { public: static const size_t page_size; @@ -79,7 +78,8 @@ class OS { static bool isLinux(); static SigAction installSignalHandler(int signo, SigAction action, SigHandler handler = NULL); - static SigAction replaceCrashHandler(SigAction action); + static SigAction replaceSigsegvHandler(SigAction action); + static SigAction replaceSigbusHandler(SigAction action); static bool sendSignalToThread(int thread_id, int signo); static void* safeAlloc(size_t size); diff --git a/ddprof-lib/src/main/cpp/os_linux.cpp b/ddprof-lib/src/main/cpp/os_linux.cpp index ff41061df..017cfc6c0 100644 --- a/ddprof-lib/src/main/cpp/os_linux.cpp +++ b/ddprof-lib/src/main/cpp/os_linux.cpp @@ -244,7 +244,7 @@ SigAction OS::installSignalHandler(int signo, SigAction action, SigHandler handl return oldsa.sa_sigaction; } -SigAction OS::replaceCrashHandler(SigAction action) { +SigAction OS::replaceSigsegvHandler(SigAction action) { struct sigaction sa; sigaction(SIGSEGV, NULL, &sa); SigAction old_action = sa.sa_sigaction; @@ -253,6 +253,15 @@ SigAction OS::replaceCrashHandler(SigAction action) { return old_action; } +SigAction OS::replaceSigbusHandler(SigAction action) { + struct sigaction sa; + sigaction(SIGBUS, NULL, &sa); + SigAction old_action = sa.sa_sigaction; + sa.sa_sigaction = action; + sigaction(SIGBUS, &sa, NULL); + return old_action; +} + bool OS::sendSignalToThread(int thread_id, int signo) { return syscall(__NR_tgkill, processId(), thread_id, signo) == 0; } diff --git a/ddprof-lib/src/main/cpp/os_macos.cpp b/ddprof-lib/src/main/cpp/os_macos.cpp index 3924d4ae3..d5b64549d 100644 --- a/ddprof-lib/src/main/cpp/os_macos.cpp +++ b/ddprof-lib/src/main/cpp/os_macos.cpp @@ -214,7 +214,16 @@ SigAction OS::installSignalHandler(int signo, SigAction action, SigHandler handl return oldsa.sa_sigaction; } -SigAction OS::replaceCrashHandler(SigAction action) { +SigAction OS::replaceSigsegvHandler(SigAction action) { + struct sigaction sa; + sigaction(SIGSEGV, NULL, &sa); + SigAction old_action = sa.sa_sigaction; + sa.sa_sigaction = action; + sigaction(SIGSEGV, &sa, NULL); + return old_action; +} + +SigAction OS::replaceSigbusHandler(SigAction action) { struct sigaction sa; sigaction(SIGBUS, NULL, &sa); SigAction old_action = sa.sa_sigaction; diff --git a/ddprof-lib/src/main/cpp/profiler.cpp b/ddprof-lib/src/main/cpp/profiler.cpp index 13c38b5ea..dd240d306 100644 --- a/ddprof-lib/src/main/cpp/profiler.cpp +++ b/ddprof-lib/src/main/cpp/profiler.cpp @@ -52,6 +52,7 @@ Profiler* const Profiler::_instance = new Profiler(); static void (*orig_trapHandler)(int signo, siginfo_t* siginfo, void* ucontext); static void (*orig_segvHandler)(int signo, siginfo_t* siginfo, void* ucontext); +static void (*orig_busHandler)(int signo, siginfo_t* siginfo, void* ucontext); static Engine noop_engine; static PerfEvents perf_events; @@ -841,6 +842,18 @@ void Profiler::trapHandler(int signo, siginfo_t* siginfo, void* ucontext) { } void Profiler::segvHandler(int signo, siginfo_t* siginfo, void* ucontext) { + if (!crashHandler(signo, siginfo, ucontext)) { + orig_segvHandler(signo, siginfo, ucontext); + } +} + +void Profiler::busHandler(int signo, siginfo_t* siginfo, void* ucontext) { + if (!crashHandler(signo, siginfo, ucontext)) { + orig_busHandler(signo, siginfo, ucontext); + } +} + +bool Profiler::crashHandler(int signo, siginfo_t* siginfo, void* ucontext) { StackFrame frame(ucontext); uintptr_t pc = frame.pc(); @@ -850,7 +863,7 @@ void Profiler::segvHandler(int signo, siginfo_t* siginfo, void* ucontext) { frame.pc() += length; frame.retval() = 0; Counters::increment(HANDLED_SIGSEGV_SAFEFETCH); - return; + return true; } length = SafeAccess::skipLoadArg(pc); @@ -859,21 +872,21 @@ void Profiler::segvHandler(int signo, siginfo_t* siginfo, void* ucontext) { frame.pc() += length; frame.retval() = frame.arg1(); Counters::increment(HANDLED_SIGSEGV_SAFEFETCH); - return; + return true; } StackWalker::checkFault(); // Workaround for JDK-8313796. Setting cstack=dwarf also helps if (VMStructs::isInterpretedFrameValidFunc((const void*)pc) && frame.skipFaultInstruction()) { - return; + return true; } if (WX_MEMORY && Trap::isFaultInstruction(pc)) { - return; + return true; } - orig_segvHandler(signo, siginfo, ucontext); + return false; } void Profiler::setupSignalHandlers() { @@ -883,7 +896,8 @@ void Profiler::setupSignalHandlers() { } if (VM::java_version() > 0) { // HotSpot and J9 tolerate interposed SIGSEGV/SIGBUS handler; other JVMs probably not - orig_segvHandler = OS::replaceCrashHandler(segvHandler); + orig_segvHandler = OS::replaceSigsegvHandler(segvHandler); + orig_busHandler = OS::replaceSigbusHandler(busHandler); } } diff --git a/ddprof-lib/src/main/cpp/profiler.h b/ddprof-lib/src/main/cpp/profiler.h index 385bfd4f0..acaea04d8 100644 --- a/ddprof-lib/src/main/cpp/profiler.h +++ b/ddprof-lib/src/main/cpp/profiler.h @@ -189,6 +189,8 @@ class Profiler { void lockAll(); void unlockAll(); + static bool crashHandler(int signo, siginfo_t* siginfo, void* ucontext); + static Profiler* const _instance; public: @@ -291,6 +293,7 @@ class Profiler { static void trapHandlerEntry(int signo, siginfo_t* siginfo, void* ucontext); void trapHandler(int signo, siginfo_t* siginfo, void* ucontext); static void segvHandler(int signo, siginfo_t* siginfo, void* ucontext); + static void busHandler(int signo, siginfo_t* siginfo, void* ucontext); static void setupSignalHandlers(); static int registerThread(int tid);