From 4e2c0ba226f29f1aecab837aa2996e71222086f5 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sun, 25 Oct 2020 03:10:05 +0300 Subject: [PATCH 1/7] Provide diagnostics on stack overflow --- src/Common/ThreadStatus.cpp | 39 +++++++++++++++++++++++++++++++++++++ src/Functions/trap.cpp | 10 +++++++--- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/Common/ThreadStatus.cpp b/src/Common/ThreadStatus.cpp index bac0559fc6b..7c62117af2f 100644 --- a/src/Common/ThreadStatus.cpp +++ b/src/Common/ThreadStatus.cpp @@ -4,10 +4,13 @@ #include #include #include +#include #include #include +#include + namespace DB { @@ -22,6 +25,9 @@ namespace ErrorCodes thread_local ThreadStatus * current_thread = nullptr; thread_local ThreadStatus * main_thread = nullptr; +alignas(4096) static thread_local char alt_stack[4096]; +static thread_local bool has_alt_stack = false; + ThreadStatus::ThreadStatus() : thread_id{getThreadId()} @@ -35,6 +41,39 @@ ThreadStatus::ThreadStatus() /// NOTE: It is important not to do any non-trivial actions (like updating ProfileEvents or logging) before ThreadStatus is created /// Otherwise it could lead to SIGSEGV due to current_thread dereferencing + + /// Will set alternative signal stack to provide diagnostics for stack overflow errors. + /// If not already installed for current thread. + if (!has_alt_stack) + { + /// Don't repeat tries even if not installed successfully. + has_alt_stack = true; + + /// We have to call 'sigaltstack' before first 'sigaction'. (It does not work other way, for unknown reason). + stack_t altstack_description{ .ss_sp = alt_stack, .ss_flags = 0, .ss_size = sizeof(alt_stack) }; + if (0 != sigaltstack(&altstack_description, nullptr)) + { + LOG_WARNING(log, "Cannot set alternative signal stack for thread, {}", errnoToString(errno)); + } + else + { + /// Obtain existing sigaction and modify it by adding a flag. + struct sigaction action{}; + if (0 != sigaction(SIGSEGV, nullptr, &action)) + { + LOG_WARNING(log, "Cannot obtain previous signal action to set alternative signal stack for thread, {}", errnoToString(errno)); + } + else if (!(action.sa_flags & SA_ONSTACK)) + { + action.sa_flags |= SA_ONSTACK; + + if (0 != sigaction(SIGSEGV, &action, nullptr)) + { + LOG_WARNING(log, "Cannot set action with alternative signal stack for thread, {}", errnoToString(errno)); + } + } + } + } } ThreadStatus::~ThreadStatus() diff --git a/src/Functions/trap.cpp b/src/Functions/trap.cpp index 34553f4b266..505e16411cc 100644 --- a/src/Functions/trap.cpp +++ b/src/Functions/trap.cpp @@ -61,9 +61,9 @@ public: return std::make_shared(); } - [[clang::optnone]] void executeImpl(Block & columns, const ColumnNumbers & arguments, size_t result, size_t input_rows_count) const override + [[clang::optnone]] ColumnPtr executeImpl(ColumnsWithTypeAndName & block, const DataTypePtr & result_type, size_t input_rows_count) const override { - if (const ColumnConst * column = checkAndGetColumnConst(columns[arguments[0]].column.get())) + if (const ColumnConst * column = checkAndGetColumnConst(block[0].column.get())) { String mode = column->getValue(); @@ -135,6 +135,10 @@ public: { (void)context.getCurrentQueryId(); } + else if (mode == "stack overflow") + { + executeImpl(block, result_type, input_rows_count); + } else if (mode == "mmap many") { std::vector maps; @@ -160,7 +164,7 @@ public: else throw Exception("The only argument for function " + getName() + " must be constant String", ErrorCodes::ILLEGAL_COLUMN); - columns[result].column = columns[result].type->createColumnConst(input_rows_count, 0ULL); + return result_type->createColumnConst(input_rows_count, 0ULL); } }; From 068235c2d7a92143117f30607eb38d16b5ceb2b1 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Mon, 26 Oct 2020 05:18:36 +0300 Subject: [PATCH 2/7] Disable alt stack for sanitizers --- programs/server/Server.cpp | 2 +- src/Common/ThreadStatus.cpp | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/programs/server/Server.cpp b/programs/server/Server.cpp index b85cb5e75f2..0dd0330c2c2 100644 --- a/programs/server/Server.cpp +++ b/programs/server/Server.cpp @@ -277,7 +277,7 @@ int Server::main(const std::vector & /*args*/) LOG_WARNING(log, "Server was built in debug mode. It will work slowly."); #endif -#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER) +#if defined(SANITIZER) LOG_WARNING(log, "Server was built with sanitizer. It will work slowly."); #endif diff --git a/src/Common/ThreadStatus.cpp b/src/Common/ThreadStatus.cpp index 7c62117af2f..55792314d07 100644 --- a/src/Common/ThreadStatus.cpp +++ b/src/Common/ThreadStatus.cpp @@ -25,8 +25,10 @@ namespace ErrorCodes thread_local ThreadStatus * current_thread = nullptr; thread_local ThreadStatus * main_thread = nullptr; -alignas(4096) static thread_local char alt_stack[4096]; -static thread_local bool has_alt_stack = false; +#if !defined(SANITIZER) + alignas(4096) static thread_local char alt_stack[4096]; + static thread_local bool has_alt_stack = false; +#endif ThreadStatus::ThreadStatus() @@ -44,6 +46,7 @@ ThreadStatus::ThreadStatus() /// Will set alternative signal stack to provide diagnostics for stack overflow errors. /// If not already installed for current thread. +#if !defined(SANITIZER) /// Sanitizer makes larger stack usage and/or confused by alternative stack. if (!has_alt_stack) { /// Don't repeat tries even if not installed successfully. @@ -74,6 +77,7 @@ ThreadStatus::ThreadStatus() } } } +#endif } ThreadStatus::~ThreadStatus() From 88e846b36d01a121ff50f11d96d42dbf25f1c706 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Mon, 26 Oct 2020 07:42:22 +0300 Subject: [PATCH 3/7] Fix build on Mac OS --- src/Common/ThreadStatus.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Common/ThreadStatus.cpp b/src/Common/ThreadStatus.cpp index 55792314d07..bd063b43fad 100644 --- a/src/Common/ThreadStatus.cpp +++ b/src/Common/ThreadStatus.cpp @@ -53,7 +53,11 @@ ThreadStatus::ThreadStatus() has_alt_stack = true; /// We have to call 'sigaltstack' before first 'sigaction'. (It does not work other way, for unknown reason). - stack_t altstack_description{ .ss_sp = alt_stack, .ss_flags = 0, .ss_size = sizeof(alt_stack) }; + stack_t altstack_description{}; + altstack_description.ss_sp = alt_stack; + altstack_description.ss_flags = 0; + altstack_description.ss_size = sizeof(alt_stack); + if (0 != sigaltstack(&altstack_description, nullptr)) { LOG_WARNING(log, "Cannot set alternative signal stack for thread, {}", errnoToString(errno)); From 0ba2fa81058b19148dcc002fb7445d11b517a3ed Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Mon, 26 Oct 2020 11:56:30 +0300 Subject: [PATCH 4/7] Fix "Arcadia" --- src/Common/ThreadStatus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Common/ThreadStatus.cpp b/src/Common/ThreadStatus.cpp index bd063b43fad..48132991fab 100644 --- a/src/Common/ThreadStatus.cpp +++ b/src/Common/ThreadStatus.cpp @@ -46,7 +46,7 @@ ThreadStatus::ThreadStatus() /// Will set alternative signal stack to provide diagnostics for stack overflow errors. /// If not already installed for current thread. -#if !defined(SANITIZER) /// Sanitizer makes larger stack usage and/or confused by alternative stack. +#if !defined(SANITIZER) && !defined(ARCADIA_BUILD) /// Sanitizer makes larger stack usage and/or confused by alternative stack. if (!has_alt_stack) { /// Don't repeat tries even if not installed successfully. From a591d1f32afcb8e7eb0b69583523cc726ad1a719 Mon Sep 17 00:00:00 2001 From: alexey-milovidov Date: Mon, 26 Oct 2020 22:46:25 +0300 Subject: [PATCH 5/7] Update ThreadStatus.cpp --- src/Common/ThreadStatus.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Common/ThreadStatus.cpp b/src/Common/ThreadStatus.cpp index 48132991fab..81ad364e801 100644 --- a/src/Common/ThreadStatus.cpp +++ b/src/Common/ThreadStatus.cpp @@ -25,7 +25,7 @@ namespace ErrorCodes thread_local ThreadStatus * current_thread = nullptr; thread_local ThreadStatus * main_thread = nullptr; -#if !defined(SANITIZER) +#if !defined(SANITIZER) && !defined(ARCADIA_BUILD) alignas(4096) static thread_local char alt_stack[4096]; static thread_local bool has_alt_stack = false; #endif @@ -46,7 +46,8 @@ ThreadStatus::ThreadStatus() /// Will set alternative signal stack to provide diagnostics for stack overflow errors. /// If not already installed for current thread. -#if !defined(SANITIZER) && !defined(ARCADIA_BUILD) /// Sanitizer makes larger stack usage and/or confused by alternative stack. + /// Sanitizer makes larger stack usage and also it's incompatible with alternative stack by default (it sets up and relies on its own). +#if !defined(SANITIZER) && !defined(ARCADIA_BUILD) if (!has_alt_stack) { /// Don't repeat tries even if not installed successfully. From 4e8978e02222a2810a3e698f4203f2d12931c08e Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 17 Dec 2020 05:21:27 +0300 Subject: [PATCH 6/7] Merge with master --- src/Functions/trap.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Functions/trap.cpp b/src/Functions/trap.cpp index 505e16411cc..7cd7d7c8c00 100644 --- a/src/Functions/trap.cpp +++ b/src/Functions/trap.cpp @@ -1,4 +1,4 @@ -#if 0 +#if 1 #include #include @@ -61,7 +61,8 @@ public: return std::make_shared(); } - [[clang::optnone]] ColumnPtr executeImpl(ColumnsWithTypeAndName & block, const DataTypePtr & result_type, size_t input_rows_count) const override + [[clang::optnone]] + ColumnPtr executeImpl(const ColumnsWithTypeAndName & block, const DataTypePtr & result_type, size_t input_rows_count) const override { if (const ColumnConst * column = checkAndGetColumnConst(block[0].column.get())) { From 01d3aef89096564bf399efc8b8616fe7b3a9a48d Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Thu, 17 Dec 2020 05:53:43 +0300 Subject: [PATCH 7/7] Disable trap back --- src/Functions/trap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Functions/trap.cpp b/src/Functions/trap.cpp index 7cd7d7c8c00..38cf53948e6 100644 --- a/src/Functions/trap.cpp +++ b/src/Functions/trap.cpp @@ -1,4 +1,4 @@ -#if 1 +#if 0 #include #include