示例#1
0
/**
 * This is the signal-handler routine that is performed in case of a signal. It
 * distinguishes:
 * - synchronous:
 *     - exceptions
 * - asynchronous:
 *     - exceptions
 *     - quits (termination requests).
 *
 * @remarks Do not perform any signal-handling context unsafe operations in this
 * function.
 */
static void
signalHandler(
    int sig,
    siginfo_t *info,
    void* uap)
{
    struct sig_context sync;
    struct sig_context sigInfo;

    sigInfo.info = *info;
#ifdef OS_HAS_UCONTEXT_T
    sigInfo.uc = *(ucontext_t *)uap;
#endif

    /* WARNING: Don't do any async/signalling-unsafe calls here (so refrain from
     * using OS_REPORT_X and the like). */
    if (sigismember(&exceptionsMask, sig) == 1 && sigInfo.info.si_code != SI_USER) {
        os_sigaction *xo;
        /* We have an exception (synchronous) here. The assumption is
         * that exception don't occur in middleware-code, so we can
         * synchronously call the signalHandlerThread in order to detach user-
         * layer from all Domains (kernels). */
        signalHandlerThreadNotify(sigInfo, &sync);
        /* BEWARE: This may be an interleaved handling of an exception, so use
         * sync from now on instead of sigInfo.*/

        /* Reset the original signal-handler. Since the exception was
         * synchronous, running out of this handler will regenerate the signal,
         * which will then be handled by the original signal-handler. */
        xo = &old_signalHandler[sync.info.si_signo];
        os_sigactionSet(sync.info.si_signo, xo, NULL);
    } else {
        /* Pass signal to signal-handler thread for asynchronous handling */
        signalHandlerThreadNotify(sigInfo, NULL);
    }
}
示例#2
0
/**
 * This is the signal-handler routine that is performed in case of a signal. It
 * distinguishes:
 * - synchronous:
 *     - exceptions
 * - asynchronous:
 *     - exceptions
 *     - quits (termination requests).
 *
 * @remarks Do not perform any signal-handling context unsafe operations in this
 * function.
 */
static void
signalHandler(
    int sig,
    siginfo_t *info,
    void* uap)
{
    struct sig_context sync;
    struct sig_context sigInfo;
    os_signalHandlerCallbackInfo *cbInfo = os__signalHandlerGetCallbackInfo();

    /* info can be NULL on Solaris */
    if (info == NULL) {
        /* Pretend that it was an SI_USER signal. */
        memset(&sigInfo.info, 0, sizeof(siginfo_t));
        sigInfo.info.si_signo = sig;
        sigInfo.info.si_code = SI_USER;
        sigInfo.info.si_pid = getpid();
        sigInfo.info.si_uid = getuid();
    } else {
        sigInfo.info = *info;
    }
    sigInfo.ThreadIdSignalRaised = os_threadIdToInteger(os_threadIdSelf());
    sigInfo.domainId = os_reportGetDomain();
#ifdef OS_HAS_UCONTEXT_T
    sigInfo.uc = *(ucontext_t *)uap;
#endif

    /* WARNING: Don't do any async/signalling-unsafe calls here (so refrain from
     * using OS_REPORT_X and the like). */
    if (sigismember(&exceptionsMask, sig) == 1 && sigInfo.info.si_code != SI_USER){
        os_sigaction *xo;

        if (inSignalHandlerThread()) {
            /* The signalHandlerThread caught an exception (synchronous)
             * itself. The fact that the signalHandlerThread caught an
             * exception means there is a bug in the error handling code. */
            const char panicmsg[] = "FATAL ERROR: Synchronously trapped signal in signalHandlerThread\n";
            panic(panicmsg, sizeof(panicmsg) - 1);
            /* This line will not be reached anymore */
        }

        /* Grab the Mutex for the ExceptionHandler stack and hold it during
         * the processing of the exception. This way you avoid handlers
         * being added or removed right in between writing the exception
         * context into the pipe and the signal handler thread reading it
         * and handling it from the pipe. Also you avoid another signal from
         * another thread overwriting our context.
         * To visualize the the duration for this mutex claim, the resulting
         * handler code has been placed in its own (indented) scope.
         */
        {
            os_mutexLock(&cbInfo->exceptionMtx);

            /* Obtain the context of the thread that called the signalHandler.
             * This information will be needed by the callback invoked by the
             * signalHandlerThread, to decide what kind of action needs to
             * be taken.
             */
            os__signalHandlerExceptionGetThreadContextCallbackInvoke(cbInfo);

            /* We have an exception (synchronous) here. The assumption is
             * that exception don't occur in middleware-code, so we can
             * synchronously call the signalHandlerThread in order to detach user-
             * layer from all Domains (kernels). */
            signalHandlerThreadNotify(sigInfo, &sync);

            os_mutexUnlock(&cbInfo->exceptionMtx);
        }

        /* BEWARE: This may be an interleaved handling of an exception, so use
         * sync from now on instead of sigInfo.*/

        /* Reset the original signal-handler. If the exception was synchronous,
         * running out of this handler will regenerate the signal, which will
         * then be handled by the original signal-handler. Otherwise it needs
         * to be re-raised. */
        xo = &old_signalHandler[sync.info.si_signo];
        os_sigactionSet(sync.info.si_signo, xo, NULL);

        /* Positive values are reserved for kernel-generated signals, i.e.,
         * actual synchronous hard errors. The rest are 'soft' errors and thus
         * need to be re-raised. */
        if(sigInfo.info.si_code <= 0){
            raise(sig);
        }
    } else {
        /* Pass signal to signal-handler thread for asynchronous handling */
        os_uint32 index = pa_inc32_nv(&cbInfo->exitRequestInsertionIndex) % EXIT_REQUEST_BUFFER_SIZE;
        os__signalHandlerExitRequestGetThreadContextCallbackInvoke(cbInfo, index);
        signalHandlerThreadNotify(sigInfo, NULL);
    }
}