Example #1
0
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);
}
Example #2
0
static void signalHandler_npe_so(int signum, siginfo_t* info, void* context) {
    // SIGSEGV/SIGBUS are synchronous signals so we shouldn't have to worry about only calling
    // async-signal-safe functions here.
    Env* env = rvmGetEnv();
    if (env && rvmIsNonNativeFrame(env)) {
        // We now know the fault occurred in non-native code.
        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) {
            Frame fakeFrame;
            fakeFrame.prev = (Frame*) getFramePointer((ucontext_t*) context);
            fakeFrame.returnAddress = getPC((ucontext_t*) context);
            Object* throwable = NULL;
            CallStack* callStack = captureCallStackFromFrame(env, &fakeFrame);
            if (callStack) {
                throwable = rvmAllocateObject(env, exClass);
                if (throwable) {
                    rvmCallVoidClassMethod(env, exClass, throwableInitMethod, throwable, PTR_TO_LONG(callStack));
                    if (rvmExceptionCheck(env)) {
                        throwable = NULL;
                    }
                }
            }
            if (!throwable) {
                throwable = rvmExceptionClear(env);
            }
            rvmRaiseException(env, throwable); // Never returns!
        }
    }
}
Example #3
0
static void signalHandler_dump_thread(int signum, siginfo_t* info, void* context) {
    Env* env = rvmGetEnv();
    if (env) {
        Frame fakeFrame;
        if (rvmIsNonNativeFrame(env)) {
            // Signalled in non-native code
            fakeFrame.prev = (Frame*) getFramePointer((ucontext_t*) context);
            fakeFrame.returnAddress = getPC((ucontext_t*) context);
        } else {
            // The thread was signalled while in native code, possibly a system 
            // function. We cannot trust that this code uses proper frame 
            // pointers so we cannot use the context's frame pointer. The top
            // most GatewayFrame in env was pushed when native code was entered.
            // Use its frame as frame pointer.
            fakeFrame = *(Frame*) env->gatewayFrames->frameAddress;
        }

        captureCallStack(env, &fakeFrame, dumpThreadStackTraceCallStack, MAX_CALL_STACK_LENGTH);
    }
    sem_post(&dumpThreadStackTraceCallSemaphore);
}