Commit c1beec58 authored by Dan Melnic's avatar Dan Melnic Committed by Facebook GitHub Bot

Add support for specifying which fatal signals to handle

Summary: Add support for specifying which fatal signals to handle

Reviewed By: simpkins

Differential Revision: D20672281

fbshipit-source-id: 16696abcf551efcd932f5b56b336d6c5bc0d7a55
parent 91a0da83
......@@ -40,6 +40,10 @@
namespace folly {
namespace symbolizer {
const unsigned long kAllFatalSignals = (1UL << SIGSEGV) | (1UL << SIGILL) |
(1UL << SIGFPE) | (1UL << SIGABRT) | (1UL << SIGBUS) | (1UL << SIGTERM) |
(1UL << SIGQUIT);
namespace {
/**
......@@ -489,7 +493,7 @@ bool isSmallSigAltStackEnabled() {
} // namespace
void installFatalSignalHandler() {
void installFatalSignalHandler(std::bitset<64> signals) {
if (gAlreadyInstalled.exchange(true)) {
// Already done.
return;
......@@ -530,7 +534,10 @@ void installFatalSignalHandler() {
sa.sa_sigaction = &signalHandler;
for (auto p = kFatalSignals; p->name; ++p) {
CHECK_ERR(sigaction(p->number, &sa, &p->oldAction));
if ((p->number < static_cast<int>(signals.size())) &&
signals.test(p->number)) {
CHECK_ERR(sigaction(p->number, &sa, &p->oldAction));
}
}
}
} // namespace symbolizer
......
......@@ -16,19 +16,27 @@
#pragma once
#include <bitset>
#include <functional>
namespace folly {
namespace symbolizer {
extern const unsigned long kAllFatalSignals;
/**
* Install handler for fatal signals. The list of signals being handled is in
* SignalHandler.cpp.
*
* The handler will dump signal and time information followed by a stack trace
* to stderr, and then call the callbacks registered below.
*
* The signals parameter can be used to specify only specific fatal signals for
* which the handler should be installed. Only signals from kAllFatalSignals
* are honored in this list, other signals are ignored.
*/
void installFatalSignalHandler();
void installFatalSignalHandler(
std::bitset<64> signals = std::bitset<64>(kAllFatalSignals));
/**
* Add a callback to be run when receiving a fatal signal. They will also
......
......@@ -32,12 +32,26 @@
DEFINE_string(logging, "", "Logging configuration");
namespace folly {
const unsigned long kAllFatalSignals =
#if FOLLY_USE_SYMBOLIZER
symbolizer::kAllFatalSignals;
#else
0;
#endif
InitOptions::InitOptions() noexcept : fatal_signals(kAllFatalSignals) {}
void init(int* argc, char*** argv, bool removeFlags) {
InitOptions options;
options.removeFlags(removeFlags);
init(argc, argv, options);
}
void init(int* argc, char*** argv, InitOptions options) {
#if FOLLY_USE_SYMBOLIZER
// Install the handler now, to trap errors received during startup.
// The callbacks, if any, can be installed later
folly::symbolizer::installFatalSignalHandler();
folly::symbolizer::installFatalSignalHandler(options.fatal_signals);
#elif !defined(_WIN32)
google::InstallFailureSignalHandler();
#endif
......@@ -51,9 +65,9 @@ void init(int* argc, char*** argv, bool removeFlags) {
folly::SingletonVault::singleton()->registrationComplete();
#if !FOLLY_HAVE_LIBGFLAGS
(void)removeFlags;
(void)options;
#else
gflags::ParseCommandLineFlags(argc, argv, removeFlags);
gflags::ParseCommandLineFlags(argc, argv, options.remove_flags);
#endif
folly::initLoggingOrDie(FLAGS_logging);
......@@ -76,6 +90,10 @@ Init::Init(int* argc, char*** argv, bool removeFlags) {
init(argc, argv, removeFlags);
}
Init::Init(int* argc, char*** argv, InitOptions options) {
init(argc, argv, options);
}
Init::~Init() {
SingletonVault::singleton()->destroyInstances();
}
......
......@@ -15,8 +15,34 @@
*/
#pragma once
#include <folly/CPortability.h>
#include <bitset>
namespace folly {
class InitOptions {
public:
InitOptions() noexcept;
bool remove_flags{true};
// mask of all fatal (default handler of terminating the process) signals for
// which `init()` will install handler that print stack traces and invokes
// previously established handler (or terminate if there were none).
// Signals that are not in `symbolizer::kAllFatalSignals` will be ignored
// if passed here
// Defaults to all signal in `symbolizer::kAllFatalSignals`
std::bitset<64> fatal_signals;
InitOptions& removeFlags(bool remove) {
remove_flags = remove;
return *this;
}
InitOptions& fatalSignals(unsigned long val) {
fatal_signals = val;
return *this;
}
};
/*
* Calls common init functions in the necessary order
......@@ -27,11 +53,13 @@
* @param argc, argv arguments to your main
* @param removeFlags if true, will update argc,argv to remove recognized
* gflags passed on the command line
* @param options options
*/
namespace folly {
void init(int* argc, char*** argv, bool removeFlags = true);
void init(int* argc, char*** argv, InitOptions options);
/*
* An RAII object to be constructed at the beginning of main() and destructed
* implicitly at the end of main().
......@@ -48,6 +76,9 @@ class Init {
public:
// Force ctor & dtor out of line for better stack traces even with LTO.
FOLLY_NOINLINE Init(int* argc, char*** argv, bool removeFlags = true);
FOLLY_NOINLINE Init(int* argc, char*** argv, InitOptions options);
FOLLY_NOINLINE ~Init();
Init(Init const&) = delete;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment