Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 29 additions & 24 deletions Fleece/Support/Backtrace+signals-posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ namespace fleece {

for ( const int signal : signals) {
struct sigaction action{};
action.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_NODEFER | SA_RESETHAND;
// NOTE: No SA_RESETHAND since on managed platforms signals are recoverable and
// we want our handler to keep working in the event that they are not
action.sa_flags = SA_SIGINFO | SA_ONSTACK;
sigfillset(&action.sa_mask);
sigdelset(&action.sa_mask, signal);
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
Expand All @@ -91,11 +92,11 @@ namespace fleece {
unique_ptr<byte[]> _stack_content;

#ifdef __APPLE__
static constexpr array<int, 11> signals = {
#else
static constexpr array<int, 10> signals = {
#else
static constexpr array<int, 9> signals = {
#endif
SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGQUIT, SIGSEGV, SIGSYS, SIGTRAP, SIGXCPU, SIGXFSZ,
SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGQUIT, SIGSEGV, SIGSYS, SIGTRAP, SIGXFSZ,
#if defined(__APPLE__)
SIGEMT,
#endif
Expand All @@ -111,37 +112,41 @@ namespace fleece {
NOINLINE static void crash_handler_immediate(siginfo_t* info, void* context) {
void* buffer[50];
int n = Backtrace::raw_capture(buffer, 50, context);
const char* name = strsignal(info->si_signo);
write_to_and_stderr(sLogFD, "\n\n******************** Process Crash: ", 38);
if ( name ) {
write_to_and_stderr(sLogFD, name);
} else {
write_to_and_stderr(sLogFD, "Signal: ", 8);
write_long(info->si_signo, sLogFD);
}
write_to_and_stderr(sLogFD, "\n\n******************** Signal caught: ", 38);
write_long(info->si_signo, sLogFD);

write_to_and_stderr(sLogFD, " Timestamp: ", 12);
char timestamp[20];
snprintf(timestamp, 20, "%lld", static_cast<long long>(time(nullptr)));
write_long(time(nullptr), sLogFD);

write_to_and_stderr(sLogFD, " *******************\n", 21);
Backtrace::writeTo(buffer + 3, n - 3, sLogFD);
write_to_and_stderr(sLogFD, "\n******************** Now terminating ********************\n", 59);
if ( sLogFD != -1 ) {
fsync(sLogFD);
close(sLogFD);
}
}

[[noreturn]] static void sig_handler(int signo, siginfo_t* info, void* context) {
crash_handler_immediate(info, context);

auto default_action = BacktraceSignalHandlerPosix::defaultActionFor(signo);
sigaction(signo, &default_action, nullptr);
raise(signo);
static void chain_to_previous(int signo, siginfo_t* info, void* context) {
const auto& prev = defaultActionFor(signo);
if ((prev.sa_flags & SA_SIGINFO) && prev.sa_sigaction && prev.sa_sigaction != &sig_handler) {
// Original fault context: the runtime can recover (and modify *context,
// which our return then resumes into) or die inside this call.
prev.sa_sigaction(signo, info, context);
} else if (prev.sa_handler && prev.sa_handler != SIG_IGN
&& prev.sa_handler != SIG_DFL) {
// SIG_IGN and SIG_DFL are not actual functions, don't try to call them
prev.sa_handler(signo);
} else if (prev.sa_handler == SIG_DFL) {
sigaction(signo, &prev, nullptr); // restore default and let it act
raise(signo); // fatal default terminates here
}
//SIG_IGN means ignore, so do just that
}

_exit(128 + signo);
static void sig_handler(int signo, siginfo_t* info, void* context) {
crash_handler_immediate(info, context);
chain_to_previous(signo, info, context);
write_to_and_stderr(sLogFD,
"\n********** Signal handled; execution continuing **********\n", 60);
}
};

Expand Down
24 changes: 10 additions & 14 deletions cmake/platform_linux.cmake
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
include("${CMAKE_CURRENT_LIST_DIR}/platform_base.cmake")
include(CheckCXXSourceCompiles)

# libbacktrace is bundled inside GCC's private library directory.
# Ask GCC where it keeps the library and header so that builds with
# other compilers (e.g. Clang) can find it.
find_program(_gcc NAMES gcc)
if(_gcc)
# Both GCC and Clang support -print-file-name to locate bundled libraries.
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
execute_process(
COMMAND ${_gcc} -print-file-name=libbacktrace.a
OUTPUT_VARIABLE _gcc_bt_lib OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
if(_gcc_bt_lib AND NOT _gcc_bt_lib STREQUAL "libbacktrace.a")
get_filename_component(_gcc_lib_dir "${_gcc_bt_lib}" DIRECTORY)
find_path(BACKTRACE_INCLUDE_DIR backtrace.h HINTS "${_gcc_lib_dir}/include")
COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=libbacktrace.a
OUTPUT_VARIABLE _bt_lib OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET)
if(_bt_lib AND NOT _bt_lib STREQUAL "libbacktrace.a")
get_filename_component(_bt_lib_dir "${_bt_lib}" DIRECTORY)
find_path(BACKTRACE_INCLUDE_DIR backtrace.h HINTS "${_bt_lib_dir}/include")
if(BACKTRACE_INCLUDE_DIR)
set(BACKTRACE_LIBRARY "${_gcc_bt_lib}")
set(BACKTRACE_LIBRARY "${_bt_lib}")
set(CMAKE_REQUIRED_INCLUDES "${BACKTRACE_INCLUDE_DIR}")
set(CMAKE_REQUIRED_LIBRARIES "${BACKTRACE_LIBRARY}")
check_cxx_source_compiles("
Expand All @@ -26,11 +23,10 @@ if(_gcc)
unset(CMAKE_REQUIRED_INCLUDES)
unset(CMAKE_REQUIRED_LIBRARIES)
endif()
unset(_bt_lib_dir)
endif()
unset(_gcc_bt_lib)
unset(_gcc_lib_dir)
unset(_bt_lib)
endif()
unset(_gcc)

function(set_source_files)
set(oneValueArgs RESULT)
Expand Down
Loading