1
0
Fork 0

Avoid some exceptions in environment feature when reading files. (#8834)

The changes have been added to reduce the noise during startup.
This commit is contained in:
Jan Christoph Uhde 2019-04-26 10:21:34 +02:00 committed by Jan
parent 79461852b5
commit 89449df97d
3 changed files with 191 additions and 139 deletions

View File

@ -46,9 +46,12 @@ void EnvironmentFeature::prepare() {
#ifdef __linux__
try {
if (basics::FileUtils::exists("/proc/version")) {
std::string value =
basics::StringUtils::trim(basics::FileUtils::slurp("/proc/version"));
LOG_TOPIC("75ddc", INFO, Logger::FIXME) << "detected operating system: " << value;
std::string content;
auto rv = basics::FileUtils::slurp("/proc/version", content);
if (rv.ok()) {
std::string value = basics::StringUtils::trim(content);
LOG_TOPIC("75ddc", INFO, Logger::FIXME) << "detected operating system: " << value;
}
}
} catch (...) {
// ignore any errors as the log output is just informational
@ -76,54 +79,60 @@ void EnvironmentFeature::prepare() {
// check overcommit_memory & overcommit_ratio
try {
std::string value =
basics::FileUtils::slurp("/proc/sys/vm/overcommit_memory");
uint64_t v = basics::StringUtils::uint64(value);
std::string content;
auto rv = basics::FileUtils::slurp("/proc/sys/vm/overcommit_memory", content);
if (rv.ok()) {
uint64_t v = basics::StringUtils::uint64(content);
if (v == 2) {
if (v == 2) {
#ifdef ARANGODB_HAVE_JEMALLOC
LOG_TOPIC("fadc5", WARN, arangodb::Logger::MEMORY)
<< "/proc/sys/vm/overcommit_memory is set to a value of 2. this setting has been found to be problematic";
LOG_TOPIC("d08d6", WARN, Logger::MEMORY)
<< "execute 'sudo bash -c \"echo 0 > "
<< "/proc/sys/vm/overcommit_memory\"'";
LOG_TOPIC("fadc5", WARN, arangodb::Logger::MEMORY)
<< "/proc/sys/vm/overcommit_memory is set to a value of 2. this "
"setting has been found to be problematic";
LOG_TOPIC("d08d6", WARN, Logger::MEMORY)
<< "execute 'sudo bash -c \"echo 0 > "
<< "/proc/sys/vm/overcommit_memory\"'";
#endif
// from https://www.kernel.org/doc/Documentation/sysctl/vm.txt:
//
// When this flag is 0, the kernel attempts to estimate the amount
// of free memory left when userspace requests more memory.
// When this flag is 1, the kernel pretends there is always enough
// memory until it actually runs out.
// When this flag is 2, the kernel uses a "never overcommit"
// policy that attempts to prevent any overcommit of memory.
std::string ratio =
basics::FileUtils::slurp("/proc/sys/vm/overcommit_ratio");
uint64_t r = basics::StringUtils::uint64(ratio);
// from https://www.kernel.org/doc/Documentation/sysctl/vm.txt:
//
// When overcommit_memory is set to 2, the committed address
// space is not permitted to exceed swap plus this percentage
// of physical RAM.
// from https://www.kernel.org/doc/Documentation/sysctl/vm.txt:
//
// When this flag is 0, the kernel attempts to estimate the amount
// of free memory left when userspace requests more memory.
// When this flag is 1, the kernel pretends there is always enough
// memory until it actually runs out.
// When this flag is 2, the kernel uses a "never overcommit"
// policy that attempts to prevent any overcommit of memory.
rv = basics::FileUtils::slurp("/proc/sys/vm/overcommit_ratio", content);
if (rv.ok()) {
uint64_t r = basics::StringUtils::uint64(content);
// from https://www.kernel.org/doc/Documentation/sysctl/vm.txt:
//
// When overcommit_memory is set to 2, the committed address
// space is not permitted to exceed swap plus this percentage
// of physical RAM.
struct sysinfo info;
int res = sysinfo(&info);
if (res == 0) {
double swapSpace = static_cast<double>(info.totalswap);
double ram = static_cast<double>(TRI_PhysicalMemory);
double rr = (ram >= swapSpace) ? 100.0 * ((ram - swapSpace) / ram) : 0.0;
if (static_cast<double>(r) < 0.99 * rr) {
LOG_TOPIC("b0a75", WARN, Logger::MEMORY)
<< "/proc/sys/vm/overcommit_ratio is set to '" << r
<< "'. It is recommended to set it to at least '" << std::llround(rr)
<< "' (100 * (max(0, (RAM - Swap Space)) / RAM)) to utilize all "
<< "available RAM. Setting it to this value will minimize swap "
<< "usage, but may result in more out-of-memory errors, while "
<< "setting it to 100 will allow the system to use both all "
<< "available RAM and swap space.";
LOG_TOPIC("1041e", WARN, Logger::MEMORY)
<< "execute 'sudo bash -c \"echo " << std::llround(rr) << " > "
<< "/proc/sys/vm/overcommit_ratio\"'";
struct sysinfo info;
int res = sysinfo(&info);
if (res == 0) {
double swapSpace = static_cast<double>(info.totalswap);
double ram = static_cast<double>(TRI_PhysicalMemory);
double rr = (ram >= swapSpace) ? 100.0 * ((ram - swapSpace) / ram) : 0.0;
if (static_cast<double>(r) < 0.99 * rr) {
LOG_TOPIC("b0a75", WARN, Logger::MEMORY)
<< "/proc/sys/vm/overcommit_ratio is set to '" << r
<< "'. It is recommended to set it to at least '"
<< std::llround(rr) << "' (100 * (max(0, (RAM - Swap Space)) / RAM)) to utilize all "
<< "available RAM. Setting it to this value will minimize "
"swap "
<< "usage, but may result in more out-of-memory errors, "
"while "
<< "setting it to 100 will allow the system to use both all "
<< "available RAM and swap space.";
LOG_TOPIC("1041e", WARN, Logger::MEMORY)
<< "execute 'sudo bash -c \"echo " << std::llround(rr) << " > "
<< "/proc/sys/vm/overcommit_ratio\"'";
}
}
}
}
}
@ -143,23 +152,24 @@ void EnvironmentFeature::prepare() {
// test local ipv4 port range
try {
std::string value =
basics::FileUtils::slurp("/proc/sys/net/ipv4/ip_local_port_range");
std::string content;
auto rv = basics::FileUtils::slurp("/proc/sys/net/ipv4/ip_local_port_range", content);
if (rv.ok()) {
std::vector<std::string> parts = basics::StringUtils::split(content, '\t');
if (parts.size() == 2) {
uint64_t lower = basics::StringUtils::uint64(parts[0]);
uint64_t upper = basics::StringUtils::uint64(parts[1]);
std::vector<std::string> parts = basics::StringUtils::split(value, '\t');
if (parts.size() == 2) {
uint64_t lower = basics::StringUtils::uint64(parts[0]);
uint64_t upper = basics::StringUtils::uint64(parts[1]);
if (lower > upper || (upper - lower) < 16384) {
LOG_TOPIC("721da", WARN, arangodb::Logger::COMMUNICATION)
<< "local port range for ipv4/ipv6 ports is " << lower << " - " << upper
<< ", which does not look right. it is recommended to make at "
"least 16K ports available";
LOG_TOPIC("eb911", WARN, Logger::MEMORY)
<< "execute 'sudo bash -c \"echo -e \\\"32768\\t60999\\\" > "
"/proc/sys/net/ipv4/ip_local_port_range\"' or use an even "
"bigger port range";
if (lower > upper || (upper - lower) < 16384) {
LOG_TOPIC("721da", WARN, arangodb::Logger::COMMUNICATION)
<< "local port range for ipv4/ipv6 ports is " << lower << " - " << upper
<< ", which does not look right. it is recommended to make at "
"least 16K ports available";
LOG_TOPIC("eb911", WARN, Logger::MEMORY)
<< "execute 'sudo bash -c \"echo -e \\\"32768\\t60999\\\" > "
"/proc/sys/net/ipv4/ip_local_port_range\"' or use an even "
"bigger port range";
}
}
}
} catch (...) {
@ -170,17 +180,19 @@ void EnvironmentFeature::prepare() {
// https://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux
// https://stackoverflow.com/questions/8893888/dropping-of-connections-with-tcp-tw-recycle
try {
std::string value =
basics::FileUtils::slurp("/proc/sys/net/ipv4/tcp_tw_recycle");
uint64_t v = basics::StringUtils::uint64(value);
if (v != 0) {
LOG_TOPIC("c277c", WARN, Logger::COMMUNICATION)
<< "/proc/sys/net/ipv4/tcp_tw_recycle is enabled (" << v << ")"
<< "'. This can lead to all sorts of \"random\" network problems. "
<< "It is advised to leave it disabled (should be kernel default)";
LOG_TOPIC("29333", WARN, Logger::COMMUNICATION)
<< "execute 'sudo bash -c \"echo 0 > "
"/proc/sys/net/ipv4/tcp_tw_recycle\"'";
std::string content;
auto rv = basics::FileUtils::slurp("/proc/sys/net/ipv4/tcp_tw_recycle", content);
if (rv.ok()) {
uint64_t v = basics::StringUtils::uint64(content);
if (v != 0) {
LOG_TOPIC("c277c", WARN, Logger::COMMUNICATION)
<< "/proc/sys/net/ipv4/tcp_tw_recycle is enabled (" << v << ")"
<< "'. This can lead to all sorts of \"random\" network problems. "
<< "It is advised to leave it disabled (should be kernel default)";
LOG_TOPIC("29333", WARN, Logger::COMMUNICATION)
<< "execute 'sudo bash -c \"echo 0 > "
"/proc/sys/net/ipv4/tcp_tw_recycle\"'";
}
}
} catch (...) {
// file not found or value not convertible into integer
@ -219,24 +231,26 @@ void EnvironmentFeature::prepare() {
// test zone_reclaim_mode
try {
std::string value =
basics::FileUtils::slurp("/proc/sys/vm/zone_reclaim_mode");
uint64_t v = basics::StringUtils::uint64(value);
if (v != 0) {
// from https://www.kernel.org/doc/Documentation/sysctl/vm.txt:
//
// This is value ORed together of
// 1 = Zone reclaim on
// 2 = Zone reclaim writes dirty pages out
// 4 = Zone reclaim swaps pages
//
// https://www.poempelfox.de/blog/2010/03/19/
LOG_TOPIC("7a7af", WARN, Logger::PERFORMANCE)
<< "/proc/sys/vm/zone_reclaim_mode is set to '" << v
<< "'. It is recommended to set it to a value of 0";
LOG_TOPIC("11b2b", WARN, Logger::PERFORMANCE)
<< "execute 'sudo bash -c \"echo 0 > "
"/proc/sys/vm/zone_reclaim_mode\"'";
std::string content;
auto rv = basics::FileUtils::slurp("/proc/sys/vm/zone_reclaim_mode", content);
if (rv.ok()) {
uint64_t v = basics::StringUtils::uint64(content);
if (v != 0) {
// from https://www.kernel.org/doc/Documentation/sysctl/vm.txt:
//
// This is value ORed together of
// 1 = Zone reclaim on
// 2 = Zone reclaim writes dirty pages out
// 4 = Zone reclaim swaps pages
//
// https://www.poempelfox.de/blog/2010/03/19/
LOG_TOPIC("7a7af", WARN, Logger::PERFORMANCE)
<< "/proc/sys/vm/zone_reclaim_mode is set to '" << v
<< "'. It is recommended to set it to a value of 0";
LOG_TOPIC("11b2b", WARN, Logger::PERFORMANCE)
<< "execute 'sudo bash -c \"echo 0 > "
"/proc/sys/vm/zone_reclaim_mode\"'";
}
}
} catch (...) {
// file not found or value not convertible into integer
@ -249,19 +263,22 @@ void EnvironmentFeature::prepare() {
for (auto file : paths) {
try {
std::string value = basics::FileUtils::slurp(file);
size_t start = value.find('[');
size_t end = value.find(']');
std::string value;
auto rv = basics::FileUtils::slurp(file, value);
if (rv.ok()) {
size_t start = value.find('[');
size_t end = value.find(']');
if (start != std::string::npos && end != std::string::npos &&
start < end && end - start >= 4) {
value = value.substr(start + 1, end - start - 1);
if (value == "always") {
LOG_TOPIC("e8b68", WARN, Logger::MEMORY)
<< file << " is set to '" << value
<< "'. It is recommended to set it to a value of 'never' "
"or 'madvise'";
showHuge = true;
if (start != std::string::npos && end != std::string::npos &&
start < end && end - start >= 4) {
value = value.substr(start + 1, end - start - 1);
if (value == "always") {
LOG_TOPIC("e8b68", WARN, Logger::MEMORY)
<< file << " is set to '" << value
<< "'. It is recommended to set it to a value of 'never' "
"or 'madvise'";
showHuge = true;
}
}
}
} catch (...) {
@ -280,19 +297,22 @@ void EnvironmentFeature::prepare() {
if (numa) {
try {
std::string value = basics::FileUtils::slurp("/proc/self/numa_maps");
auto values = basics::StringUtils::split(value, '\n', '\0');
std::string content;
auto rv = basics::FileUtils::slurp("/proc/self/numa_maps", content);
if (rv.ok()) {
auto values = basics::StringUtils::split(content, '\n', '\0');
if (!values.empty()) {
auto first = values[0];
auto where = first.find(' ');
if (!values.empty()) {
auto first = values[0];
auto where = first.find(' ');
if (where != std::string::npos &&
!StringUtils::isPrefix(first.substr(where), " interleave")) {
LOG_TOPIC("3e451", WARN, Logger::MEMORY)
<< "It is recommended to set NUMA to interleaved.";
LOG_TOPIC("b25a4", WARN, Logger::MEMORY)
<< "put 'numactl --interleave=all' in front of your command";
if (where != std::string::npos &&
!StringUtils::isPrefix(first.substr(where), " interleave")) {
LOG_TOPIC("3e451", WARN, Logger::MEMORY)
<< "It is recommended to set NUMA to interleaved.";
LOG_TOPIC("b25a4", WARN, Logger::MEMORY)
<< "put 'numactl --interleave=all' in front of your command";
}
}
}
} catch (...) {
@ -302,31 +322,33 @@ void EnvironmentFeature::prepare() {
// check kernel ASLR settings
try {
std::string value =
basics::FileUtils::slurp("/proc/sys/kernel/randomize_va_space");
uint64_t v = basics::StringUtils::uint64(value);
// from man proc:
//
// 0 No randomization. Everything is static.
// 1 Conservative randomization. Shared libraries, stack, mmap(), VDSO and
// heap are randomized. 2 Full randomization. In addition to elements
// listed in the previous point, memory managed through brk() is also
// randomized.
char const* s = nullptr;
switch (v) {
case 0:
s = "nothing";
break;
case 1:
s = "shared libraries, stack, mmap, VDSO and heap";
break;
case 2:
s = "shared libraries, stack, mmap, VDSO, heap and memory managed "
"through brk()";
break;
}
if (s != nullptr) {
LOG_TOPIC("63a7a", DEBUG, Logger::FIXME) << "host ASLR is in use for " << s;
std::string content;
auto rv = basics::FileUtils::slurp("/proc/sys/kernel/randomize_va_space", content);
if (rv.ok()) {
uint64_t v = basics::StringUtils::uint64(content);
// from man proc:
//
// 0 No randomization. Everything is static.
// 1 Conservative randomization. Shared libraries, stack, mmap(), VDSO
// and heap are randomized. 2 Full randomization. In addition to
// elements listed in the previous point, memory managed through brk() is
// also randomized.
char const* s = nullptr;
switch (v) {
case 0:
s = "nothing";
break;
case 1:
s = "shared libraries, stack, mmap, VDSO and heap";
break;
case 2:
s = "shared libraries, stack, mmap, VDSO, heap and memory managed "
"through brk()";
break;
}
if (s != nullptr) {
LOG_TOPIC("63a7a", DEBUG, Logger::FIXME) << "host ASLR is in use for " << s;
}
}
} catch (...) {
// file not found or value not convertible into integer

View File

@ -204,6 +204,35 @@ void slurp(std::string const& filename, StringBuffer& result) {
fillStringBuffer(fd, filename, result, chunkSize);
}
Result slurpNoEx(std::string const& filename, StringBuffer& result) {
int fd = TRI_OPEN(filename.c_str(), O_RDONLY | TRI_O_CLOEXEC);
if (fd == -1) {
TRI_set_errno(TRI_ERROR_SYS_ERROR);
int res = TRI_errno();
std::string message("read failed for file '" + filename + "': " + strerror(res));
LOG_TOPIC("a1898", TRACE, arangodb::Logger::FIXME) << message;
return {TRI_ERROR_SYS_ERROR, message};
}
TRI_DEFER(TRI_CLOSE(fd));
result.reset();
constexpr size_t chunkSize = 8192;
fillStringBuffer(fd, filename, result, chunkSize);
return {};
}
Result slurp(std::string const& filename, std::string& result) {
constexpr size_t chunkSize = 8192;
StringBuffer buffer(chunkSize, false);
auto status = slurpNoEx(filename, buffer);
result = std::string(buffer.data(), buffer.length());
return status;
}
static void throwFileWriteError(std::string const& filename) {
TRI_set_errno(TRI_ERROR_SYS_ERROR);

View File

@ -60,6 +60,7 @@ inline std::string buildFilename(std::string const& path,
// reads file into string or buffer
std::string slurp(std::string const& filename);
void slurp(std::string const& filename, StringBuffer& result);
Result slurp(std::string const& filename, std::string& result);
// creates file and writes string to it
void spit(std::string const& filename, char const* ptr, size_t len, bool sync = false);