bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { assert(this->is_Java_thread(), "must be JavaThread"); JavaThread* jt = (JavaThread *)this; // last_Java_frame is always walkable and safe use it if we have it if (jt->has_last_Java_frame()) { *fr_addr = jt->pd_last_frame(); return true; } ucontext_t* uc = (ucontext_t*) ucontext; // We always want to use the initial frame we create from the ucontext as // it certainly signals where we currently are. However that frame may not // be safe for calling sender. In that case if we have a last_Java_frame // then the forte walker will switch to that frame as the virtual sender // for the frame we create here which is not sender safe. intptr_t* ret_fp; intptr_t* ret_sp; ExtendedPC addr = os::Solaris::fetch_frame_from_ucontext(this, uc, &ret_sp, &ret_fp); // Something would really have to be screwed up to get a NULL pc if (addr.pc() == NULL) { assert(false, "NULL pc from signal handler!"); return false; } // If sp and fp are nonsense just leave them out if (!jt->on_local_stack((address)ret_sp)) { ret_sp = NULL; ret_fp = NULL; } else { // sp is reasonable is fp reasonable? if ((address)ret_fp >= jt->stack_base() || ret_fp < ret_sp) { ret_fp = NULL; } } frame ret_frame(ret_sp, ret_fp, addr.pc()); *fr_addr = ret_frame; return true; }
extern "C" JNIEXPORT int JVM_handle_linux_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrecognized) { ucontext_t* uc = (ucontext_t*) ucVoid; Thread* t = Thread::current_or_null_safe(); SignalHandlerMark shm(t); // handle SafeFetch faults if (sig == SIGSEGV || sig == SIGBUS) { sigjmp_buf* const pjb = get_jmp_buf_for_continuation(); if (pjb) { siglongjmp(*pjb, 1); } } // Note: it's not uncommon that JNI code uses signal/sigset to // install then restore certain signal handler (e.g. to temporarily // block SIGPIPE, or have a SIGILL handler when detecting CPU // type). When that happens, JVM_handle_linux_signal() might be // invoked with junk info/ucVoid. To avoid unnecessary crash when // libjsig is not preloaded, try handle signals that do not require // siginfo/ucontext first. if (sig == SIGPIPE || sig == SIGXFSZ) { // allow chained handler to go first if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } else { // Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219 return true; } } JavaThread* thread = NULL; VMThread* vmthread = NULL; if (os::Linux::signal_handlers_are_installed) { if (t != NULL ){ if(t->is_Java_thread()) { thread = (JavaThread*)t; } else if(t->is_VM_thread()){ vmthread = (VMThread *)t; } } } if (info != NULL && thread != NULL) { // Handle ALL stack overflow variations here if (sig == SIGSEGV) { address addr = (address) info->si_addr; // check if fault address is within thread stack if (thread->on_local_stack(addr)) { // stack overflow if (thread->in_stack_yellow_reserved_zone(addr)) { thread->disable_stack_yellow_reserved_zone(); ShouldNotCallThis(); } else if (thread->in_stack_red_zone(addr)) { thread->disable_stack_red_zone(); ShouldNotCallThis(); } else { // Accessing stack address below sp may cause SEGV if // current thread has MAP_GROWSDOWN stack. This should // only happen when current thread was created by user // code with MAP_GROWSDOWN flag and then attached to VM. // See notes in os_linux.cpp. if (thread->osthread()->expanding_stack() == 0) { thread->osthread()->set_expanding_stack(); if (os::Linux::manually_expand_stack(thread, addr)) { thread->osthread()->clear_expanding_stack(); return true; } thread->osthread()->clear_expanding_stack(); } else { fatal("recursive segv. expanding stack."); } } } } /*if (thread->thread_state() == _thread_in_Java) { ShouldNotCallThis(); } else*/ if (thread->thread_state() == _thread_in_vm && sig == SIGBUS && thread->doing_unsafe_access()) { ShouldNotCallThis(); } // jni_fast_Get<Primitive>Field can trap at certain pc's if a GC // kicks in and the heap gets shrunk before the field access. /*if (sig == SIGSEGV || sig == SIGBUS) { address addr = JNI_FastGetField::find_slowcase_pc(pc); if (addr != (address)-1) { stub = addr; } }*/ // Check to see if we caught the safepoint code in the process // of write protecting the memory serialization page. It write // enables the page immediately after protecting it so we can // just return to retry the write. if (sig == SIGSEGV && os::is_memory_serialize_page(thread, (address) info->si_addr)) { // Block current thread until permission is restored. os::block_on_serialize_page_trap(); return true; } } // signal-chaining if (os::Linux::chained_handler(sig, info, ucVoid)) { return true; } if (!abort_if_unrecognized) { // caller wants another chance, so give it to him return false; } #ifndef PRODUCT if (sig == SIGSEGV) { fatal("\n#" "\n# /--------------------\\" "\n# | segmentation fault |" "\n# \\---\\ /--------------/" "\n# /" "\n# [-] |\\_/| " "\n# (+)=C |o o|__ " "\n# | | =-*-=__\\ " "\n# OOO c_c_(___)"); } #endif // !PRODUCT char buf[64]; sprintf(buf, "caught unhandled signal %d", sig); // Silence -Wformat-security warning for fatal() PRAGMA_DIAG_PUSH PRAGMA_FORMAT_NONLITERAL_IGNORED fatal(buf); PRAGMA_DIAG_POP return true; // silence compiler warnings }