1
0
Fork 0
arangodb/lib/Basics/ArangoGlobalContext.cpp

176 lines
5.0 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
///
/// 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
///
/// http://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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Dr. Frank Celler
////////////////////////////////////////////////////////////////////////////////
#include "ArangoGlobalContext.h"
#include "Basics/files.h"
#include "Logger/LogAppender.h"
#include "Rest/InitializeRest.h"
using namespace arangodb;
#ifndef _WIN32
static void ReopenLog(int) { LogAppender::reopen(); }
#endif
static void AbortHandler(int signum) {
TRI_PrintBacktrace();
#ifdef _WIN32
exit(255 + signum);
#else
signal(signum, SIG_DFL);
kill(getpid(), signum);
#endif
}
ArangoGlobalContext* ArangoGlobalContext::CONTEXT = nullptr;
ArangoGlobalContext::ArangoGlobalContext(int argc, char* argv[])
: _binaryName(TRI_BinaryName(argv[0])), _ret(EXIT_FAILURE) {
ADB_WindowsEntryFunction();
TRIAGENS_REST_INITIALIZE();
CONTEXT = this;
}
ArangoGlobalContext::~ArangoGlobalContext() {
CONTEXT = nullptr;
#ifndef _WIN32
signal(SIGHUP, SIG_IGN);
#endif
TRIAGENS_REST_SHUTDOWN;
ADB_WindowsExitFunction(_ret, nullptr);
}
int ArangoGlobalContext::exit(int ret) {
_ret = ret;
return _ret;
}
void ArangoGlobalContext::installHup() {
#ifndef _WIN32
signal(SIGHUP, ReopenLog);
#endif
}
void ArangoGlobalContext::installSegv() {
signal(SIGSEGV, AbortHandler);
}
void ArangoGlobalContext::maskAllSignals() {
#ifdef TRI_HAVE_POSIX_THREADS
sigset_t all;
sigfillset(&all);
pthread_sigmask(SIG_SETMASK, &all, 0);
#endif
}
void ArangoGlobalContext::unmaskStandardSignals() {
#ifdef TRI_HAVE_POSIX_THREADS
sigset_t all;
sigfillset(&all);
pthread_sigmask(SIG_UNBLOCK, &all, 0);
#endif
}
void ArangoGlobalContext::runStartupChecks() {
#ifdef __arm__
// detect alignment settings for ARM
{
// To change the alignment trap behavior, simply echo a number into
// /proc/cpu/alignment. The number is made up from various bits:
//
// bit behavior when set
// --- -----------------
//
// 0 A user process performing an unaligned memory access
// will cause the kernel to print a message indicating
// process name, pid, pc, instruction, address, and the
// fault code.
//
// 1 The kernel will attempt to fix up the user process
// performing the unaligned access. This is of course
// slow (think about the floating point emulator) and
// not recommended for production use.
//
// 2 The kernel will send a SIGBUS signal to the user process
// performing the unaligned access.
bool alignmentDetected = false;
std::string const filename("/proc/cpu/alignment");
try {
std::string const cpuAlignment =
arangodb::basics::FileUtils::slurp(filename);
auto start = cpuAlignment.find("User faults:");
if (start != std::string::npos) {
start += strlen("User faults:");
size_t end = start;
while (end < cpuAlignment.size()) {
if (cpuAlignment[end] == ' ' || cpuAlignment[end] == '\t') {
++end;
} else {
break;
}
}
while (end < cpuAlignment.size()) {
++end;
if (cpuAlignment[end] < '0' || cpuAlignment[end] > '9') {
break;
}
}
int64_t alignment =
std::stol(std::string(cpuAlignment.c_str() + start, end - start));
if ((alignment & 2) == 0) {
LOG(FATAL)
<< "possibly incompatible CPU alignment settings found in '"
<< filename << "'. this may cause arangod to abort with "
"SIGBUS. please set the value in '"
<< filename << "' to 2";
FATAL_ERROR_EXIT();
}
alignmentDetected = true;
}
} catch (...) {
// ignore that we cannot detect the alignment
LOG(TRACE)
<< "unable to detect CPU alignment settings. could not process file '"
<< filename << "'";
}
if (!alignmentDetected) {
LOG(WARN)
<< "unable to detect CPU alignment settings. could not process file '"
<< filename
<< "'. this may cause arangod to abort with SIGBUS. it may be "
"necessary to set the value in '"
<< filename << "' to 2";
}
}
#endif
}