static void sigsegvHandler()

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