/** * 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); } }
/** * 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); } }