static void signalHandler_npe_so(int signum, siginfo_t* info, void* context) { // rvmGetEnv() uses pthread_getspecific() which isn't listed as // async-signal-safe. Others (e.g. mono) do this too so we assume it is safe // in practice. Env* env = rvmGetEnv(); if (env && rvmIsNonNativeFrame(env)) { // We now know the fault occurred in non-native code and not in our // native code or in any non-async-signal-safe system function. It // should be safe to do things here that would normally be unsafe to do // in a signal handler. void* faultAddr = info->si_addr; void* stackAddr = env->currentThread->stackAddr; Class* exClass = NULL; if (faultAddr < stackAddr && faultAddr >= (void*) (stackAddr - THREAD_STACK_GUARD_SIZE)) { // StackOverflowError exClass = java_lang_StackOverflowError; } else { // At least on Linux x86 it seems like si_addr isn't always 0x0 even // if a read of address 0x0 triggered SIGSEGV so we assume // everything that isn't a stack overflow is a read of address 0x0 // and throw NullPointerException. exClass = java_lang_NullPointerException; } if (exClass) { Object* throwable = rvmAllocateObject(env, exClass); if (!throwable) { throwable = rvmExceptionClear(env); } Frame fakeFrame; fakeFrame.prev = (Frame*) getFramePointer((ucontext_t*) context); fakeFrame.returnAddress = getPC((ucontext_t*) context); CallStack* callStack = captureCallStackFromFrame(env, &fakeFrame); rvmSetLongInstanceFieldValue(env, throwable, stackStateField, PTR_TO_LONG(callStack)); rvmRaiseException(env, throwable); } } struct sigaction sa; sa.sa_flags = 0; sa.sa_handler = SIG_DFL; sigaction(signum, &sa, NULL); kill(0, signum); }
static void SetLongField(JNIEnv* env, jobject obj, jfieldID fieldID, jlong val) { rvmSetLongInstanceFieldValue((Env*) env, (Object*) obj, (InstanceField*) fieldID, val); }