tvl-depot/third_party/abseil_cpp/absl/debugging/failure_signal_handler.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

371 lines
11 KiB
C++
Raw Normal View History

//
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "absl/debugging/failure_signal_handler.h"
#include "absl/base/config.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
Export of internal Abseil changes -- dc6d2715f0415082fcc8da8bf74e74bce69b236c by Derek Mauro <dmauro@google.com>: Correctly detect C++ exceptions support on Clang for Windows PiperOrigin-RevId: 294905116 -- b43c44501b4820f4a2f396e426619bd02565707e by Derek Mauro <dmauro@google.com>: Set CMAKE_CXX_STANDARD on the MacOS CMake build PiperOrigin-RevId: 294730418 -- 184a078649167f9738da60b0f12108256bcfd67b by Abseil Team <absl-team@google.com>: No need for custom spec to deal with limited platforms. PiperOrigin-RevId: 294700133 -- b437c7f659b809fc84a45eab284265fec497a3e3 by Abseil Team <absl-team@google.com>: Not calling sigaltstack on WatchOS and TVOS since they don't allow it. PiperOrigin-RevId: 294699951 -- 23ab8dd381ee4104125dece8455bc96b81239789 by Gennadiy Rozental <rogeeff@google.com>: Replace use of atomic+global Mutex+bool with absl::call_once for Flag initialization. This simplifies the initialization logic and helps with upcoming work with value storage rework. PiperOrigin-RevId: 294654938 -- cee576163a2753c6138bc254e81de4800ea3307a by Gennadiy Rozental <rogeeff@google.com>: Separate const bits from mutable bits. Since bit field is not atomic unit for reading/writing, we can't have constant bits which are not protected by data guard to share the space with mutable bits which are protected. This CL just reorder fields in class and does not make any other changes. PiperOrigin-RevId: 294501780 -- b4d0e2ab559d04f655c93f008594562234773c15 by Abseil Team <absl-team@google.com>: Correct the comment. PiperOrigin-RevId: 294499328 -- a788cf71af6247df033298c49939ba0414d71693 by Derek Mauro <dmauro@google.com>: Move the FAQ to the top level directory PiperOrigin-RevId: 294493863 GitOrigin-RevId: dc6d2715f0415082fcc8da8bf74e74bce69b236c Change-Id: I71b0d8cd401b48d41433417858ae0d69398b6602
2020-02-13 15:52:24 +01:00
#ifdef __APPLE__
#include <TargetConditionals.h>
#endif
#ifdef ABSL_HAVE_MMAP
#include <sys/mman.h>
#endif
#include <algorithm>
#include <atomic>
#include <cerrno>
#include <csignal>
- 07191b0f52301e1e4a790e236f7b7c2fd90561ae Disambiguates computed return type of absl::optional logi... by Abseil Team <absl-team@google.com> - acd95f8ec4e6ec1587cb198c7f40af3c81094d92 Release container benchmarks. by Alex Strelnikov <strel@google.com> - 80f596b6b7c5e06453e778c16527d5a0e85f8413 Allow absl::base_internal::AtomicHook to have a default v... by Derek Mauro <dmauro@google.com> - 8402631546af8bcbd4acdf897d0cdfb805ad544a Release thread_identity benchmark. by Alex Strelnikov <strel@google.com> - 6dcb1e90fefb8556ce4654983d3a73c7585b4b99 Fix spelling error in variant.h by Abseil Team <absl-team@google.com> - faa8a81e1442018c0d400b09a595a5be55074715 Run tests from CMake. The CI is currently Linux only, fo... by Jon Cohen <cohenjon@google.com> - 745ed6db574f931f2ec3a88e964fb03a5f22f816 Internal change. by Derek Mauro <dmauro@google.com> - 23facd7d1c5f43ac8181b016ee4acc5955f048c1 absl::variant exception safety test. by Xiaoyi Zhang <zhangxy@google.com> - c18e21e7cf8f6e83ae9d90e536e886409dd6cf68 Reinstate the syntax check on time-zone abbreviations now... by Abseil Team <absl-team@google.com> - da469f4314f0c820665a2b5b9477af9462b23e42 Import CCTZ changes to internal copy. by Shaindel Schwartz <shaindel@google.com> - 44ea35843517be03ab256b69449ccfea64352621 Import CCTZ changes to internal copy. by Abseil Team <absl-team@google.com> - 55d1105312687c6093950fac831c7540f49045b5 Import CCTZ changes to internal copy. by Greg Falcon <gfalcon@google.com> - 58d7965ad274406410b6d833213eca04d41c6867 Add zoneinfo as a data dependency to the //absl/time tests. by Shaindel Schwartz <shaindel@google.com> - 6acc50146f9ff29015bfaaa5bf9900691f839da5 Change benchmark target type from cc_test to cc_binary. by Alex Strelnikov <strel@google.com> - db3fbdae8f9f285a466f7a070326b1ce43b6a0dd Update WORKSPACE for C++ microbenchmarks and release algo... by Alex Strelnikov <strel@google.com> - 0869ae168255242af651853ed01719166d8cebf6 Update to Bazel version 0.13.0. by Abseil Team <absl-team@google.com> - e507dd53ab788964207fdf27d31b72a33c296fab Add missing include of cstdio by Abseil Team <absl-team@google.com> GitOrigin-RevId: 07191b0f52301e1e4a790e236f7b7c2fd90561ae Change-Id: I90994cf2b438fbec894724dcd9b90882281eef56
2018-05-04 18:58:56 +02:00
#include <cstdio>
#include <cstring>
#include <ctime>
#include "absl/base/attributes.h"
#include "absl/base/internal/errno_saver.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/sysinfo.h"
#include "absl/debugging/internal/examine_stack.h"
#include "absl/debugging/stacktrace.h"
#ifndef _WIN32
#define ABSL_HAVE_SIGACTION
Export of internal Abseil changes -- dc6d2715f0415082fcc8da8bf74e74bce69b236c by Derek Mauro <dmauro@google.com>: Correctly detect C++ exceptions support on Clang for Windows PiperOrigin-RevId: 294905116 -- b43c44501b4820f4a2f396e426619bd02565707e by Derek Mauro <dmauro@google.com>: Set CMAKE_CXX_STANDARD on the MacOS CMake build PiperOrigin-RevId: 294730418 -- 184a078649167f9738da60b0f12108256bcfd67b by Abseil Team <absl-team@google.com>: No need for custom spec to deal with limited platforms. PiperOrigin-RevId: 294700133 -- b437c7f659b809fc84a45eab284265fec497a3e3 by Abseil Team <absl-team@google.com>: Not calling sigaltstack on WatchOS and TVOS since they don't allow it. PiperOrigin-RevId: 294699951 -- 23ab8dd381ee4104125dece8455bc96b81239789 by Gennadiy Rozental <rogeeff@google.com>: Replace use of atomic+global Mutex+bool with absl::call_once for Flag initialization. This simplifies the initialization logic and helps with upcoming work with value storage rework. PiperOrigin-RevId: 294654938 -- cee576163a2753c6138bc254e81de4800ea3307a by Gennadiy Rozental <rogeeff@google.com>: Separate const bits from mutable bits. Since bit field is not atomic unit for reading/writing, we can't have constant bits which are not protected by data guard to share the space with mutable bits which are protected. This CL just reorder fields in class and does not make any other changes. PiperOrigin-RevId: 294501780 -- b4d0e2ab559d04f655c93f008594562234773c15 by Abseil Team <absl-team@google.com>: Correct the comment. PiperOrigin-RevId: 294499328 -- a788cf71af6247df033298c49939ba0414d71693 by Derek Mauro <dmauro@google.com>: Move the FAQ to the top level directory PiperOrigin-RevId: 294493863 GitOrigin-RevId: dc6d2715f0415082fcc8da8bf74e74bce69b236c Change-Id: I71b0d8cd401b48d41433417858ae0d69398b6602
2020-02-13 15:52:24 +01:00
// Apple WatchOS and TVOS don't allow sigaltstack
#if !(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) && \
!(defined(TARGET_OS_TV) && TARGET_OS_TV)
#define ABSL_HAVE_SIGALTSTACK
#endif
#endif
namespace absl {
Export of internal Abseil changes -- c99f979ad34f155fbeeea69b88bdc7458d89a21c by Derek Mauro <dmauro@google.com>: Remove a floating point division by zero test. This isn't testing behavior related to the library, and MSVC warns about it in opt mode. PiperOrigin-RevId: 285220804 -- 68b015491f0dbf1ab547994673281abd1f34cd4b by Gennadiy Rozental <rogeeff@google.com>: This CL introduces following changes to the class FlagImpl: * We eliminate the CommandLineFlagLocks struct. Instead callback guard and callback function are combined into a single CallbackData struct, while primary data lock is stored separately. * CallbackData member of class FlagImpl is initially set to be nullptr and is only allocated and initialized when a flag's callback is being set. For most flags we do not pay for the extra space and extra absl::Mutex now. * Primary data guard is stored in data_guard_ data member. This is a properly aligned character buffer of necessary size. During initialization of the flag we construct absl::Mutex in this space using placement new call. * We now avoid extra value copy after successful attempt to parse value out of string. Instead we swap flag's current value with tentative value we just produced. PiperOrigin-RevId: 285132636 -- ed45d118fb818969eb13094cf7827c885dfc562c by Tom Manshreck <shreck@google.com>: Change null-term* (and nul-term*) to NUL-term* in comments PiperOrigin-RevId: 285036610 -- 729619017944db895ce8d6d29c1995aa2e5628a5 by Derek Mauro <dmauro@google.com>: Use the Posix implementation of thread identity on MinGW. Some versions of MinGW suffer from thread_local bugs. PiperOrigin-RevId: 285022920 -- 39a25493503c76885bc3254c28f66a251c5b5bb0 by Greg Falcon <gfalcon@google.com>: Implementation detail change. Add further ABSL_NAMESPACE_BEGIN and _END annotation macros to files in Abseil. PiperOrigin-RevId: 285012012 GitOrigin-RevId: c99f979ad34f155fbeeea69b88bdc7458d89a21c Change-Id: I4c85d3704e45d11a9ac50d562f39640a6adbedc1
2019-12-12 19:36:03 +01:00
ABSL_NAMESPACE_BEGIN
ABSL_CONST_INIT static FailureSignalHandlerOptions fsh_options;
// Resets the signal handler for signo to the default action for that
// signal, then raises the signal.
static void RaiseToDefaultHandler(int signo) {
signal(signo, SIG_DFL);
raise(signo);
}
struct FailureSignalData {
const int signo;
const char* const as_string;
#ifdef ABSL_HAVE_SIGACTION
struct sigaction previous_action;
// StructSigaction is used to silence -Wmissing-field-initializers.
using StructSigaction = struct sigaction;
#define FSD_PREVIOUS_INIT FailureSignalData::StructSigaction()
#else
void (*previous_handler)(int);
#define FSD_PREVIOUS_INIT SIG_DFL
#endif
};
ABSL_CONST_INIT static FailureSignalData failure_signal_data[] = {
{SIGSEGV, "SIGSEGV", FSD_PREVIOUS_INIT},
{SIGILL, "SIGILL", FSD_PREVIOUS_INIT},
{SIGFPE, "SIGFPE", FSD_PREVIOUS_INIT},
{SIGABRT, "SIGABRT", FSD_PREVIOUS_INIT},
{SIGTERM, "SIGTERM", FSD_PREVIOUS_INIT},
#ifndef _WIN32
{SIGBUS, "SIGBUS", FSD_PREVIOUS_INIT},
{SIGTRAP, "SIGTRAP", FSD_PREVIOUS_INIT},
#endif
};
#undef FSD_PREVIOUS_INIT
static void RaiseToPreviousHandler(int signo) {
// Search for the previous handler.
for (const auto& it : failure_signal_data) {
if (it.signo == signo) {
#ifdef ABSL_HAVE_SIGACTION
sigaction(signo, &it.previous_action, nullptr);
#else
signal(signo, it.previous_handler);
#endif
raise(signo);
return;
}
}
// Not found, use the default handler.
RaiseToDefaultHandler(signo);
}
namespace debugging_internal {
const char* FailureSignalToString(int signo) {
for (const auto& it : failure_signal_data) {
if (it.signo == signo) {
return it.as_string;
}
}
return "";
}
} // namespace debugging_internal
Export of internal Abseil changes -- dc6d2715f0415082fcc8da8bf74e74bce69b236c by Derek Mauro <dmauro@google.com>: Correctly detect C++ exceptions support on Clang for Windows PiperOrigin-RevId: 294905116 -- b43c44501b4820f4a2f396e426619bd02565707e by Derek Mauro <dmauro@google.com>: Set CMAKE_CXX_STANDARD on the MacOS CMake build PiperOrigin-RevId: 294730418 -- 184a078649167f9738da60b0f12108256bcfd67b by Abseil Team <absl-team@google.com>: No need for custom spec to deal with limited platforms. PiperOrigin-RevId: 294700133 -- b437c7f659b809fc84a45eab284265fec497a3e3 by Abseil Team <absl-team@google.com>: Not calling sigaltstack on WatchOS and TVOS since they don't allow it. PiperOrigin-RevId: 294699951 -- 23ab8dd381ee4104125dece8455bc96b81239789 by Gennadiy Rozental <rogeeff@google.com>: Replace use of atomic+global Mutex+bool with absl::call_once for Flag initialization. This simplifies the initialization logic and helps with upcoming work with value storage rework. PiperOrigin-RevId: 294654938 -- cee576163a2753c6138bc254e81de4800ea3307a by Gennadiy Rozental <rogeeff@google.com>: Separate const bits from mutable bits. Since bit field is not atomic unit for reading/writing, we can't have constant bits which are not protected by data guard to share the space with mutable bits which are protected. This CL just reorder fields in class and does not make any other changes. PiperOrigin-RevId: 294501780 -- b4d0e2ab559d04f655c93f008594562234773c15 by Abseil Team <absl-team@google.com>: Correct the comment. PiperOrigin-RevId: 294499328 -- a788cf71af6247df033298c49939ba0414d71693 by Derek Mauro <dmauro@google.com>: Move the FAQ to the top level directory PiperOrigin-RevId: 294493863 GitOrigin-RevId: dc6d2715f0415082fcc8da8bf74e74bce69b236c Change-Id: I71b0d8cd401b48d41433417858ae0d69398b6602
2020-02-13 15:52:24 +01:00
#ifdef ABSL_HAVE_SIGALTSTACK
static bool SetupAlternateStackOnce() {
#if defined(__wasm__) || defined (__asjms__)
const size_t page_mask = getpagesize() - 1;
#else
Export of internal Abseil changes. -- 5f1ab09522226336830d9ea6ef7276d37f536ac5 by Abseil Team <absl-team@google.com>: Clarify the documentation of ABSL_MUST_USE_RESULT. PiperOrigin-RevId: 221663609 -- af4c8359a20d56369fd1dce318220cf3be03ca66 by Greg Falcon <gfalcon@google.com>: Internal change PiperOrigin-RevId: 221538448 -- 487cd09bd1942bf607080deeae38fee6ce66f294 by Eric Fiselier <ericwf@google.com>: Work around emscripten bugs and missing features in absl/time:time_test. The emscripten toolchain has a couple of issues that cause time_test to fail. Specifically: 1) emscripten doesn't support signals. 2) The javascript implementation of strftime/strptime use different expansions of '%c' that mean it doesn't round-trip. PiperOrigin-RevId: 221523701 -- 5823652e6a200b97b07334bc47128dfac40e20fc by Xiaoyi Zhang <zhangxy@google.com>: Fix MSVC compiler warning by explicitly casting to char. Currently our MSVC build breaks with the following error: raw_hash_set.h(406): warning C4309: 'argument': truncation of constant value PiperOrigin-RevId: 221492585 -- c5806358320711a5efbe5c523df13e14ab53a17d by Greg Falcon <gfalcon@google.com>: Replace calls to getpagesize() with the more portable sysconf(_SC_PAGESIZE); the latter is in POSIX 1.0 and is called out in the Linux `getpagesize` man page as a more portable spelling. PiperOrigin-RevId: 221492471 -- 19ffe82851072229bb7ce73f754ffe4c18e8c575 by Abseil Team <absl-team@google.com>: Fix -Wundef error in absl/hash/internal/hash.h. PiperOrigin-RevId: 221444120 -- b30f3d0a848563b6e4ec33f3dc085831dfabb748 by Jon Cohen <cohenjon@google.com>: Import of CCTZ from GitHub. PiperOrigin-RevId: 221339736 GitOrigin-RevId: 5f1ab09522226336830d9ea6ef7276d37f536ac5 Change-Id: I96223d522d98bf6616dea88eb047c2d536eeddd0
2018-11-15 20:55:00 +01:00
const size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
#endif
size_t stack_size = (std::max(SIGSTKSZ, 65536) + page_mask) & ~page_mask;
#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
// Account for sanitizer instrumentation requiring additional stack space.
stack_size *= 5;
#endif
stack_t sigstk;
memset(&sigstk, 0, sizeof(sigstk));
sigstk.ss_size = stack_size;
#ifdef ABSL_HAVE_MMAP
#ifndef MAP_STACK
#define MAP_STACK 0
#endif
#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
#define MAP_ANONYMOUS MAP_ANON
#endif
sigstk.ss_sp = mmap(nullptr, sigstk.ss_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (sigstk.ss_sp == MAP_FAILED) {
ABSL_RAW_LOG(FATAL, "mmap() for alternate signal stack failed");
}
#else
sigstk.ss_sp = malloc(sigstk.ss_size);
if (sigstk.ss_sp == nullptr) {
ABSL_RAW_LOG(FATAL, "malloc() for alternate signal stack failed");
}
#endif
if (sigaltstack(&sigstk, nullptr) != 0) {
ABSL_RAW_LOG(FATAL, "sigaltstack() failed with errno=%d", errno);
}
return true;
}
#endif
#ifdef ABSL_HAVE_SIGACTION
// Sets up an alternate stack for signal handlers once.
// Returns the appropriate flag for sig_action.sa_flags
// if the system supports using an alternate stack.
static int MaybeSetupAlternateStack() {
Export of internal Abseil changes -- dc6d2715f0415082fcc8da8bf74e74bce69b236c by Derek Mauro <dmauro@google.com>: Correctly detect C++ exceptions support on Clang for Windows PiperOrigin-RevId: 294905116 -- b43c44501b4820f4a2f396e426619bd02565707e by Derek Mauro <dmauro@google.com>: Set CMAKE_CXX_STANDARD on the MacOS CMake build PiperOrigin-RevId: 294730418 -- 184a078649167f9738da60b0f12108256bcfd67b by Abseil Team <absl-team@google.com>: No need for custom spec to deal with limited platforms. PiperOrigin-RevId: 294700133 -- b437c7f659b809fc84a45eab284265fec497a3e3 by Abseil Team <absl-team@google.com>: Not calling sigaltstack on WatchOS and TVOS since they don't allow it. PiperOrigin-RevId: 294699951 -- 23ab8dd381ee4104125dece8455bc96b81239789 by Gennadiy Rozental <rogeeff@google.com>: Replace use of atomic+global Mutex+bool with absl::call_once for Flag initialization. This simplifies the initialization logic and helps with upcoming work with value storage rework. PiperOrigin-RevId: 294654938 -- cee576163a2753c6138bc254e81de4800ea3307a by Gennadiy Rozental <rogeeff@google.com>: Separate const bits from mutable bits. Since bit field is not atomic unit for reading/writing, we can't have constant bits which are not protected by data guard to share the space with mutable bits which are protected. This CL just reorder fields in class and does not make any other changes. PiperOrigin-RevId: 294501780 -- b4d0e2ab559d04f655c93f008594562234773c15 by Abseil Team <absl-team@google.com>: Correct the comment. PiperOrigin-RevId: 294499328 -- a788cf71af6247df033298c49939ba0414d71693 by Derek Mauro <dmauro@google.com>: Move the FAQ to the top level directory PiperOrigin-RevId: 294493863 GitOrigin-RevId: dc6d2715f0415082fcc8da8bf74e74bce69b236c Change-Id: I71b0d8cd401b48d41433417858ae0d69398b6602
2020-02-13 15:52:24 +01:00
#ifdef ABSL_HAVE_SIGALTSTACK
ABSL_ATTRIBUTE_UNUSED static const bool kOnce = SetupAlternateStackOnce();
return SA_ONSTACK;
#else
return 0;
#endif
}
static void InstallOneFailureHandler(FailureSignalData* data,
void (*handler)(int, siginfo_t*, void*)) {
struct sigaction act;
memset(&act, 0, sizeof(act));
sigemptyset(&act.sa_mask);
act.sa_flags |= SA_SIGINFO;
// SA_NODEFER is required to handle SIGABRT from
// ImmediateAbortSignalHandler().
act.sa_flags |= SA_NODEFER;
if (fsh_options.use_alternate_stack) {
act.sa_flags |= MaybeSetupAlternateStack();
}
act.sa_sigaction = handler;
ABSL_RAW_CHECK(sigaction(data->signo, &act, &data->previous_action) == 0,
"sigaction() failed");
}
#else
static void InstallOneFailureHandler(FailureSignalData* data,
void (*handler)(int)) {
data->previous_handler = signal(data->signo, handler);
ABSL_RAW_CHECK(data->previous_handler != SIG_ERR, "signal() failed");
}
#endif
static void WriteToStderr(const char* data) {
absl::base_internal::ErrnoSaver errno_saver;
absl::raw_logging_internal::SafeWriteToStderr(data, strlen(data));
}
static void WriteSignalMessage(int signo, void (*writerfn)(const char*)) {
char buf[64];
const char* const signal_string =
debugging_internal::FailureSignalToString(signo);
if (signal_string != nullptr && signal_string[0] != '\0') {
snprintf(buf, sizeof(buf), "*** %s received at time=%ld ***\n",
signal_string,
static_cast<long>(time(nullptr))); // NOLINT(runtime/int)
} else {
snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld ***\n",
signo, static_cast<long>(time(nullptr))); // NOLINT(runtime/int)
}
writerfn(buf);
}
// `void*` might not be big enough to store `void(*)(const char*)`.
struct WriterFnStruct {
void (*writerfn)(const char*);
};
// Many of the absl::debugging_internal::Dump* functions in
// examine_stack.h take a writer function pointer that has a void* arg
// for historical reasons. failure_signal_handler_writer only takes a
// data pointer. This function converts between these types.
static void WriterFnWrapper(const char* data, void* arg) {
static_cast<WriterFnStruct*>(arg)->writerfn(data);
}
// Convenient wrapper around DumpPCAndFrameSizesAndStackTrace() for signal
// handlers. "noinline" so that GetStackFrames() skips the top-most stack
// frame for this function.
ABSL_ATTRIBUTE_NOINLINE static void WriteStackTrace(
void* ucontext, bool symbolize_stacktrace,
void (*writerfn)(const char*, void*), void* writerfn_arg) {
constexpr int kNumStackFrames = 32;
void* stack[kNumStackFrames];
int frame_sizes[kNumStackFrames];
int min_dropped_frames;
int depth = absl::GetStackFramesWithContext(
stack, frame_sizes, kNumStackFrames,
1, // Do not include this function in stack trace.
ucontext, &min_dropped_frames);
absl::debugging_internal::DumpPCAndFrameSizesAndStackTrace(
absl::debugging_internal::GetProgramCounter(ucontext), stack, frame_sizes,
depth, min_dropped_frames, symbolize_stacktrace, writerfn, writerfn_arg);
}
// Called by AbslFailureSignalHandler() to write the failure info. It is
// called once with writerfn set to WriteToStderr() and then possibly
// with writerfn set to the user provided function.
static void WriteFailureInfo(int signo, void* ucontext,
void (*writerfn)(const char*)) {
WriterFnStruct writerfn_struct{writerfn};
WriteSignalMessage(signo, writerfn);
WriteStackTrace(ucontext, fsh_options.symbolize_stacktrace, WriterFnWrapper,
&writerfn_struct);
}
// absl::SleepFor() can't be used here since AbslInternalSleepFor()
// may be overridden to do something that isn't async-signal-safe on
// some platforms.
static void PortableSleepForSeconds(int seconds) {
#ifdef _WIN32
Sleep(seconds * 1000);
#else
struct timespec sleep_time;
sleep_time.tv_sec = seconds;
sleep_time.tv_nsec = 0;
while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {}
#endif
}
#ifdef ABSL_HAVE_ALARM
// AbslFailureSignalHandler() installs this as a signal handler for
// SIGALRM, then sets an alarm to be delivered to the program after a
// set amount of time. If AbslFailureSignalHandler() hangs for more than
// the alarm timeout, ImmediateAbortSignalHandler() will abort the
// program.
static void ImmediateAbortSignalHandler(int) {
RaiseToDefaultHandler(SIGABRT);
}
#endif
// absl::base_internal::GetTID() returns pid_t on most platforms, but
// returns absl::base_internal::pid_t on Windows.
using GetTidType = decltype(absl::base_internal::GetTID());
ABSL_CONST_INIT static std::atomic<GetTidType> failed_tid(0);
#ifndef ABSL_HAVE_SIGACTION
static void AbslFailureSignalHandler(int signo) {
void* ucontext = nullptr;
#else
static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {
#endif
const GetTidType this_tid = absl::base_internal::GetTID();
GetTidType previous_failed_tid = 0;
if (!failed_tid.compare_exchange_strong(
previous_failed_tid, static_cast<intptr_t>(this_tid),
std::memory_order_acq_rel, std::memory_order_relaxed)) {
ABSL_RAW_LOG(
ERROR,
"Signal %d raised at PC=%p while already in AbslFailureSignalHandler()",
signo, absl::debugging_internal::GetProgramCounter(ucontext));
if (this_tid != previous_failed_tid) {
// Another thread is already in AbslFailureSignalHandler(), so wait
// a bit for it to finish. If the other thread doesn't kill us,
// we do so after sleeping.
PortableSleepForSeconds(3);
RaiseToDefaultHandler(signo);
// The recursively raised signal may be blocked until we return.
return;
}
}
#ifdef ABSL_HAVE_ALARM
// Set an alarm to abort the program in case this code hangs or deadlocks.
if (fsh_options.alarm_on_failure_secs > 0) {
alarm(0); // Cancel any existing alarms.
signal(SIGALRM, ImmediateAbortSignalHandler);
alarm(fsh_options.alarm_on_failure_secs);
}
#endif
// First write to stderr.
WriteFailureInfo(signo, ucontext, WriteToStderr);
// Riskier code (because it is less likely to be async-signal-safe)
// goes after this point.
if (fsh_options.writerfn != nullptr) {
WriteFailureInfo(signo, ucontext, fsh_options.writerfn);
}
if (fsh_options.call_previous_handler) {
RaiseToPreviousHandler(signo);
} else {
RaiseToDefaultHandler(signo);
}
}
void InstallFailureSignalHandler(const FailureSignalHandlerOptions& options) {
fsh_options = options;
for (auto& it : failure_signal_data) {
InstallOneFailureHandler(&it, AbslFailureSignalHandler);
}
}
Export of internal Abseil changes -- c99f979ad34f155fbeeea69b88bdc7458d89a21c by Derek Mauro <dmauro@google.com>: Remove a floating point division by zero test. This isn't testing behavior related to the library, and MSVC warns about it in opt mode. PiperOrigin-RevId: 285220804 -- 68b015491f0dbf1ab547994673281abd1f34cd4b by Gennadiy Rozental <rogeeff@google.com>: This CL introduces following changes to the class FlagImpl: * We eliminate the CommandLineFlagLocks struct. Instead callback guard and callback function are combined into a single CallbackData struct, while primary data lock is stored separately. * CallbackData member of class FlagImpl is initially set to be nullptr and is only allocated and initialized when a flag's callback is being set. For most flags we do not pay for the extra space and extra absl::Mutex now. * Primary data guard is stored in data_guard_ data member. This is a properly aligned character buffer of necessary size. During initialization of the flag we construct absl::Mutex in this space using placement new call. * We now avoid extra value copy after successful attempt to parse value out of string. Instead we swap flag's current value with tentative value we just produced. PiperOrigin-RevId: 285132636 -- ed45d118fb818969eb13094cf7827c885dfc562c by Tom Manshreck <shreck@google.com>: Change null-term* (and nul-term*) to NUL-term* in comments PiperOrigin-RevId: 285036610 -- 729619017944db895ce8d6d29c1995aa2e5628a5 by Derek Mauro <dmauro@google.com>: Use the Posix implementation of thread identity on MinGW. Some versions of MinGW suffer from thread_local bugs. PiperOrigin-RevId: 285022920 -- 39a25493503c76885bc3254c28f66a251c5b5bb0 by Greg Falcon <gfalcon@google.com>: Implementation detail change. Add further ABSL_NAMESPACE_BEGIN and _END annotation macros to files in Abseil. PiperOrigin-RevId: 285012012 GitOrigin-RevId: c99f979ad34f155fbeeea69b88bdc7458d89a21c Change-Id: I4c85d3704e45d11a9ac50d562f39640a6adbedc1
2019-12-12 19:36:03 +01:00
ABSL_NAMESPACE_END
} // namespace absl