in src/Session.cpp [154:261]
static void sigsegvHandler(int signum, siginfo_t* ip, void*) {
const char* s;
/* First check for stack overflow if we know the stack position.
We assume anything within 16Mb beyond the stack end is a stack overflow.
*/
if (signum == SIGSEGV && ip != nullptr && ip != (siginfo_t*) 1 && (intptr_t) R_CStackStart != -1) {
uintptr_t addr = (uintptr_t) ip->si_addr;
intptr_t diff = (R_CStackDir > 0) ? R_CStackStart - addr : addr - R_CStackStart;
uintptr_t upper = 0x1000000; /* 16Mb */
if ((intptr_t) R_CStackLimit != -1) upper += R_CStackLimit;
if (diff > 0 && diff < upper) {
REprintf("Error: segfault from C stack overflow\n");
#if defined(linux) || defined(__linux__) || defined(__sun) || defined(sun)
sigset_t ss;
sigaddset(&ss, signum);
sigprocmask(SIG_UNBLOCK, &ss, NULL);
#endif
Rf_jump_to_toplevel();
}
}
/* need to take off stack checking as stack base has changed */
R_CStackLimit = (uintptr_t) -1;
/* Do not translate these messages */
REprintf("\n *** caught %s ***\n", signum == SIGILL ? "illegal operation" : signum == SIGBUS ? "bus error" : "segfault");
if (ip != nullptr) {
if (signum == SIGILL) {
switch (ip->si_code) {
#ifdef ILL_ILLOPC
case ILL_ILLOPC:
s = "illegal opcode";
break;
#endif
#ifdef ILL_ILLOPN
case ILL_ILLOPN:
s = "illegal operand";
break;
#endif
#ifdef ILL_ILLADR
case ILL_ILLADR:
s = "illegal addressing mode";
break;
#endif
#ifdef ILL_ILLTRP
case ILL_ILLTRP:
s = "illegal trap";
break;
#endif
#ifdef ILL_COPROC
case ILL_COPROC:
s = "coprocessor error";
break;
#endif
default:
s = "unknown";
break;
}
} else if (signum == SIGBUS)
switch (ip->si_code) {
#ifdef BUS_ADRALN
case BUS_ADRALN:
s = "invalid alignment";
break;
#endif
#ifdef BUS_ADRERR /* not on macOS, apparently */
case BUS_ADRERR:
s = "non-existent physical address";
break;
#endif
#ifdef BUS_OBJERR /* not on macOS, apparently */
case BUS_OBJERR:
s = "object specific hardware error";
break;
#endif
default:
s = "unknown";
break;
}
else
switch (ip->si_code) {
#ifdef SEGV_MAPERR
case SEGV_MAPERR:
s = "memory not mapped";
break;
#endif
#ifdef SEGV_ACCERR
case SEGV_ACCERR:
s = "invalid permissions";
break;
#endif
default:
s = "unknown";
break;
}
REprintf("address %p, cause '%s'\n", ip->si_addr, s);
}
if (!commandLineOptions.crashReportFile.empty()) {
saveRWrapperCrashReport(commandLineOptions.crashReportFile);
}
sessionManager.quit();
R_CleanTempDir();
signal(signum, SIG_DFL);
raise(signum);
}