From 09d2f1928781aaa68b858211b259c06bb2190f18 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sat, 30 May 2020 22:38:25 +0300 Subject: [PATCH 1/4] Better exception in case when there is shortage of memory mappings --- src/Common/Exception.cpp | 63 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/Common/Exception.cpp b/src/Common/Exception.cpp index 23e5e0a762e..a81ff2c7328 100644 --- a/src/Common/Exception.cpp +++ b/src/Common/Exception.cpp @@ -5,8 +5,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -25,6 +27,8 @@ namespace ErrorCodes extern const int STD_EXCEPTION; extern const int UNKNOWN_EXCEPTION; extern const int LOGICAL_ERROR; + extern const int CANNOT_ALLOCATE_MEMORY; + extern const int CANNOT_MREMAP; } @@ -156,6 +160,58 @@ static void getNoSpaceLeftInfoMessage(std::filesystem::path path, std::string & #endif } + +/** It is possible that the system has enough memory, + * but we have shortage of the number of available memory mappings. + * Provide good diagnostic to user in that case. + */ +static void getNotEnoughMemoryMessage(std::string & msg) +{ +#if defined(__linux__) + try + { + UInt64 max_map_count = 0; + { + ReadBufferFromFile file("/proc/sys/vm/max_map_count"); + readText(max_map_count, file); + } + + UInt64 num_maps = 0; + { + ReadBufferFromFile file("/proc/self/maps"); + while (!file.eof()) + { + char * next_pos = find_first_symbols<'\n'>(file.position(), file.buffer().end()); + file.position() = next_pos; + + if (!file.hasPendingData()) + continue; + + if (*file.position() == '\n') + { + ++num_maps; + ++file.position(); + } + } + } + + if (num_maps > max_map_count * 0.99) + { + msg += fmt::format( + "\nIt looks like that the process is near the limit on number of virtual memory mappings." + "\nCurrent number of mappings (/proc/self/maps): {}." + "\nLimit on number of mappings (/proc/sys/vm/max_map_count): {}." + "\nYou should increase the limit for vm.max_map_count in /etc/sysctl.conf", + num_maps, max_map_count); + } + } + catch (...) + { + msg += "\nCannot obtain additional info about memory usage."; + } +#endif +} + static std::string getExtraExceptionInfo(const std::exception & e) { String msg; @@ -170,6 +226,13 @@ static std::string getExtraExceptionInfo(const std::exception & e) { if (errno_exception->getErrno() == ENOSPC && errno_exception->getPath()) getNoSpaceLeftInfoMessage(errno_exception->getPath().value(), msg); + else if (errno_exception->code() == ErrorCodes::CANNOT_ALLOCATE_MEMORY + || errno_exception->code() == ErrorCodes::CANNOT_MREMAP) + getNotEnoughMemoryMessage(msg); + } + else if (dynamic_cast(&e)) + { + getNotEnoughMemoryMessage(msg); } } catch (...) From 9a41eb14a66fa7c0b7dcab1edee1a6552c3fde7c Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sat, 30 May 2020 22:40:23 +0300 Subject: [PATCH 2/4] Fix build --- src/Common/Exception.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Common/Exception.cpp b/src/Common/Exception.cpp index a81ff2c7328..3db73631fbb 100644 --- a/src/Common/Exception.cpp +++ b/src/Common/Exception.cpp @@ -209,6 +209,8 @@ static void getNotEnoughMemoryMessage(std::string & msg) { msg += "\nCannot obtain additional info about memory usage."; } +#else + (void)msg; #endif } From b95b6ec0ee1b92d50abf38c04300da3b17579f04 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sat, 30 May 2020 23:02:44 +0300 Subject: [PATCH 3/4] Tested with "trap" function --- src/Common/Exception.cpp | 10 +++++++--- src/Functions/trap.cpp | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Common/Exception.cpp b/src/Common/Exception.cpp index 3db73631fbb..bac30c802c1 100644 --- a/src/Common/Exception.cpp +++ b/src/Common/Exception.cpp @@ -170,15 +170,18 @@ static void getNotEnoughMemoryMessage(std::string & msg) #if defined(__linux__) try { + static constexpr size_t buf_size = 4096; + char buf[buf_size]; + UInt64 max_map_count = 0; { - ReadBufferFromFile file("/proc/sys/vm/max_map_count"); + ReadBufferFromFile file("/proc/sys/vm/max_map_count", buf_size, -1, buf); readText(max_map_count, file); } UInt64 num_maps = 0; { - ReadBufferFromFile file("/proc/self/maps"); + ReadBufferFromFile file("/proc/self/maps", buf_size, -1, buf); while (!file.eof()) { char * next_pos = find_first_symbols<'\n'>(file.position(), file.buffer().end()); @@ -201,7 +204,8 @@ static void getNotEnoughMemoryMessage(std::string & msg) "\nIt looks like that the process is near the limit on number of virtual memory mappings." "\nCurrent number of mappings (/proc/self/maps): {}." "\nLimit on number of mappings (/proc/sys/vm/max_map_count): {}." - "\nYou should increase the limit for vm.max_map_count in /etc/sysctl.conf", + "\nYou should increase the limit for vm.max_map_count in /etc/sysctl.conf" + "\n", num_maps, max_map_count); } } diff --git a/src/Functions/trap.cpp b/src/Functions/trap.cpp index a7f8d81576d..0f58d73b7fb 100644 --- a/src/Functions/trap.cpp +++ b/src/Functions/trap.cpp @@ -7,11 +7,13 @@ #include #include #include +#include #include #include #include #include +#include namespace DB @@ -132,6 +134,25 @@ public: { (void)context.getCurrentQueryId(); } + else if (mode == "mmap many") + { + std::vector maps; + SCOPE_EXIT( + { + //for (void * map : maps) + // munmap(map, 4096); + }); + + while (true) + { + void * hint = reinterpret_cast( + std::uniform_int_distribution(0x100000000000UL, 0x700000000000UL)(thread_local_rng)); + void * map = mmap(hint, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (MAP_FAILED == map) + throwFromErrno("Allocator: Cannot mmap", ErrorCodes::CANNOT_ALLOCATE_MEMORY); + maps.push_back(map); + } + } else throw Exception("Unknown trap mode", ErrorCodes::BAD_ARGUMENTS); } From 383962e47ce9a4702782514f45c02bb45b8283a2 Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Sat, 30 May 2020 23:45:30 +0300 Subject: [PATCH 4/4] Update trap.cpp --- src/Functions/trap.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Functions/trap.cpp b/src/Functions/trap.cpp index 0f58d73b7fb..94aa56919b4 100644 --- a/src/Functions/trap.cpp +++ b/src/Functions/trap.cpp @@ -24,6 +24,7 @@ namespace ErrorCodes extern const int ILLEGAL_COLUMN; extern const int ILLEGAL_TYPE_OF_ARGUMENT; extern const int BAD_ARGUMENTS; + extern const int CANNOT_ALLOCATE_MEMORY; }