source/util/SystemUtil.cpp (109 lines of code) (raw):
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "source/util/SystemUtil.h"
#include <signal.h>
#include <exception>
#include <stdexcept>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <folly/Format.h>
DECLARE_bool(help);
DECLARE_bool(helpshort);
namespace fb360_dep {
namespace system_util {
void terminateHandler() {
std::exception_ptr exptr = std::current_exception();
if (exptr != 0) {
try {
rethrow_exception(exptr);
} catch (std::exception& ex) {
LOG(FATAL) << folly::sformat("Terminated with exception: {}", ex.what());
} catch (...) {
LOG(FATAL) << "Terminated with unknown exception";
}
} else {
LOG(FATAL) << "Terminated due to unknown reason";
}
}
void sigHandler(int signal) {
#ifdef WIN32
switch (signal) {
case SIGINT:
LOG(FATAL) << "SIGINT";
break;
case SIGILL:
LOG(FATAL) << "SIGILL";
break;
case SIGFPE:
LOG(FATAL) << "SIGFPE";
break;
case SIGSEGV:
LOG(FATAL) << "SIGSEGV";
break;
case SIGTERM:
LOG(FATAL) << "SIGTERM";
break;
case SIGBREAK:
LOG(FATAL) << "SIGBREAK";
break;
case SIGABRT:
LOG(FATAL) << "SIGABRT";
break;
default:
LOG(FATAL) << "UNKNOWN SIGNAL";
break;
}
#else
LOG(FATAL) << strsignal(signal);
#endif
}
bool isSubstring(const std::string& haystack, const std::string& needle) {
return strstr(haystack.c_str(), needle.c_str()) != NULL;
}
void logFlags() {
std::vector<gflags::CommandLineFlagInfo> flags;
gflags::GetAllFlags(&flags); // flags are sorted by filename, then flagname
const std::string substring = "facebook360_dep"; // only get flags from our project
// Find name padding to align printed flag values
int padding = 0;
for (const auto& flag : flags) {
if (isSubstring(flag.filename, substring)) {
padding = std::max(padding, int(flag.name.size()));
}
}
LOG(INFO) << "Flags:";
for (const auto& flag : flags) {
if (isSubstring(flag.filename, substring)) {
LOG(INFO) << folly::sformat("--{:<*} = {}", padding, flag.name, flag.current_value);
}
}
}
void initDep(int& argc, char**& argv, const std::string kUsageMessage) {
if (kUsageMessage != "") {
gflags::SetUsageMessage(kUsageMessage);
}
// Initialize Google's logging library
google::InitGoogleLogging(argv[0]);
static const bool kRemoveFlags = true;
gflags::ParseCommandLineNonHelpFlags(&argc, &argv, kRemoveFlags);
FLAGS_helpshort |= FLAGS_help;
FLAGS_help = false;
gflags::HandleCommandLineHelpFlags();
if (FLAGS_log_dir != "") {
::filesystem::create_directories(FLAGS_log_dir);
}
logFlags();
// setup signal and termination handlers
std::set_terminate(terminateHandler);
// terminate process: interrupt program
signal(SIGINT, sigHandler);
// create core image: illegal instruction
signal(SIGILL, sigHandler);
// create core image: floating-point exception
signal(SIGFPE, sigHandler);
// create core image: segmentation violation
signal(SIGSEGV, sigHandler);
// terminate process: software termination signal
signal(SIGTERM, sigHandler);
#ifndef WIN32
// terminate process: terminal line hangup
signal(SIGHUP, sigHandler);
// create core image: quit program
signal(SIGQUIT, sigHandler);
// create core image: trace trap
signal(SIGTRAP, sigHandler);
// terminate process: kill program
signal(SIGKILL, sigHandler);
// create core image: bus error
signal(SIGBUS, sigHandler);
// create core image: non-existent system call invoked
signal(SIGSYS, sigHandler);
// terminate process: write on a pipe with no reader
signal(SIGPIPE, sigHandler);
#endif
}
} // namespace system_util
} // namespace fb360_dep