summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBilly Donahue <billy.donahue@mongodb.com>2020-01-24 22:20:23 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-02-05 21:00:41 +0000
commit969151e9ab69dcb53397cf40f810e718421db081 (patch)
treeeb7d4cd83e4c70df67d87847b6e269f05bd75929
parent2985a71befe421902b5d15e9567e3b449e65ecdd (diff)
downloadmongo-969151e9ab69dcb53397cf40f810e718421db081.tar.gz
SERVER-45677 libunwind on by default where possible
- SCons configure to probe for libunwind support - gracefully handle SIGUSR2 without libunwind - integrate libunwind on-by-default (linux-x86_64) into evergreen
-rw-r--r--SConstruct49
-rw-r--r--etc/evergreen.yml26
-rw-r--r--src/mongo/SConscript3
-rw-r--r--src/mongo/config.h.in3
-rw-r--r--src/mongo/util/signal_handlers.cpp21
-rw-r--r--src/mongo/util/signal_handlers_synchronous.cpp4
-rw-r--r--src/mongo/util/signal_handlers_synchronous.h6
-rw-r--r--src/mongo/util/stacktrace.h3
-rw-r--r--src/mongo/util/stacktrace_bm.cpp6
-rw-r--r--src/mongo/util/stacktrace_posix.cpp2
-rw-r--r--src/mongo/util/stacktrace_test.cpp2
-rw-r--r--src/mongo/util/tcmalloc_parameters.idl4
-rw-r--r--src/third_party/SConscript4
-rw-r--r--src/third_party/unwind/SConscript2
14 files changed, 93 insertions, 42 deletions
diff --git a/SConstruct b/SConstruct
index 007f8311205..b3cd3fa1174 100644
--- a/SConstruct
+++ b/SConstruct
@@ -505,10 +505,10 @@ add_option('msvc-debugging-format',
)
add_option('use-libunwind',
- choices=["on", "off"],
+ choices=["on", "off", "auto"],
const="on",
- default="off",
- help="Enable libunwind for backtraces (experimental)",
+ default="auto",
+ help="Enable libunwind for backtraces",
nargs="?",
type='choice',
)
@@ -1018,17 +1018,6 @@ usemozjs = (jsEngine.startswith('mozjs'))
if not serverJs and not usemozjs:
print("Warning: --server-js=off is not needed with --js-engine=none")
-use_libunwind = get_option("use-libunwind") == "on"
-if use_libunwind:
- use_system_libunwind = use_system_version_of_library("libunwind")
- use_vendored_libunwind = not use_system_libunwind
-else:
- if use_system_version_of_library("libunwind"):
- print("Error: --use-system-libunwind requires --use-libunwind")
- Exit(1)
-
- use_system_libunwind = use_vendored_libunwind = False
-
# We defer building the env until we have determined whether we want certain values. Some values
# in the env actually have semantics for 'None' that differ from being absent, so it is better
# to build it up via a dict, and then construct the Environment in one shot with kwargs.
@@ -1373,6 +1362,38 @@ link_model = get_option('link-model')
if link_model == "auto":
link_model = "static"
+# libunwind configuration.
+# In which the following globals are set and normalized to bool:
+# - use_libunwind
+# - use_system_libunwind
+# - use_vendored_libunwind
+use_libunwind = get_option("use-libunwind")
+use_system_libunwind = use_system_version_of_library("libunwind")
+
+# Assume system libunwind works if it's installed and selected.
+# Vendored libunwind, however, works only on linux-x86_64.
+can_use_libunwind = (use_system_libunwind or
+ env.TargetOSIs('linux') and env['TARGET_ARCH'] == 'x86_64')
+
+if use_libunwind == "off":
+ use_libunwind = False
+ use_system_libunwind = False
+elif use_libunwind == "on":
+ use_libunwind = True
+ if not can_use_libunwind:
+ env.ConfError("libunwind not supported on target platform")
+ Exit(1)
+elif use_libunwind == "auto":
+ use_libunwind = can_use_libunwind
+
+use_vendored_libunwind = use_libunwind and not use_system_libunwind
+if use_system_libunwind and not use_libunwind:
+ print("Error: --use-system-libunwind requires --use-libunwind")
+ Exit(1)
+if use_libunwind == True:
+ env.SetConfigHeaderDefine("MONGO_CONFIG_USE_LIBUNWIND")
+
+
# Windows can't currently support anything other than 'object' or 'static', until
# we have both hygienic builds and have annotated functions for export.
if env.TargetOSIs('windows') and link_model not in ['object', 'static', 'dynamic-sdk']:
diff --git a/etc/evergreen.yml b/etc/evergreen.yml
index 92f572029cf..e1b95a53fe8 100644
--- a/etc/evergreen.yml
+++ b/etc/evergreen.yml
@@ -353,7 +353,7 @@ variables:
- enterprise-rhel-67-s390x
- enterprise-rhel-70-64-bit
- enterprise-rhel-70-64-bit-kitchen-sink
- - enterprise-rhel-70-64-bit-libunwind
+ - enterprise-rhel-70-64-bit-no-libunwind
- enterprise-rhel-71-ppc64le
- enterprise-rhel-71-ppc64le-inmem
- enterprise-rhel-72-s390x
@@ -8498,6 +8498,7 @@ buildvariants:
- name: .jscore .common
- name: jsCore_txns_large_txns_format
- name: jsonSchema
+ - name: libunwind_tests
- name: .logical_session_cache
- name: .multi_shard
- name: multi_stmt_txn_jscore_passthrough_with_migration_gen
@@ -8589,6 +8590,7 @@ buildvariants:
- name: free_monitoring
- name: .jscore .common
- name: .jstestfuzz .common
+ - name: libunwind_tests
- name: .logical_session_cache .one_sec
- name: multiversion
- name: replica_sets
@@ -8641,6 +8643,7 @@ buildvariants:
- name: jsCore_auth
- name: .jstestfuzz .common
- name: .jstestfuzz_multiversion_gen
+ - name: libunwind_tests
- name: .logical_session_cache .one_sec
- name: .multiversion_fuzzer
- name: .multiversion_passthrough
@@ -8696,6 +8699,7 @@ buildvariants:
- ubuntu1604-build
- name: .jscore .common
- name: .jstestfuzz .common
+ - name: libunwind_tests
- name: .logical_session_cache .one_sec
- name: multiversion
- name: .powercycle
@@ -9013,6 +9017,7 @@ buildvariants:
- name: .encrypt !.aggregation
- name: .jscore .common !.compat
- name: .jstestfuzz .common
+ - name: libunwind_tests
- name: .logical_session_cache .one_sec
- name: noPassthrough_gen
- name: noPassthroughWithMongod_gen
@@ -9066,6 +9071,7 @@ buildvariants:
- name: free_monitoring
- name: .jscore .common
- name: .jstestfuzz .common
+ - name: libunwind_tests
- name: .logical_session_cache .one_sec
- name: multiversion
- name: replica_sets
@@ -9118,6 +9124,7 @@ buildvariants:
- name: .encrypt !.aggregation
- name: .jscore .common !.compat
- name: .jstestfuzz .common
+ - name: libunwind_tests
- name: .logical_session_cache .one_sec
- name: noPassthrough_gen
- name: noPassthroughWithMongod_gen
@@ -9174,6 +9181,7 @@ buildvariants:
- name: free_monitoring
- name: .jscore .common
- name: .jstestfuzz .common
+ - name: libunwind_tests
- name: .logical_session_cache .one_sec
- name: multiversion
- name: replica_sets
@@ -9751,6 +9759,7 @@ buildvariants:
- name: jsCore_txns_large_txns_format
- name: jsonSchema
- name: .jstestfuzz
+ - name: libunwind_tests
- name: .logical_session_cache
- name: mqlrun
- name: .multi_shard
@@ -10155,6 +10164,7 @@ buildvariants:
- name: jsCore_minimum_batch_size
- name: jsCore_op_query
- name: .jstestfuzz_multiversion_gen
+ - name: libunwind_tests
- name: .logical_session_cache .one_sec
- name: .multi_shard .common
- name: multiversion
@@ -10216,6 +10226,7 @@ buildvariants:
- name: .jscore .common !.compat !.decimal !.sharding
- name: jsCore_txns_large_txns_format
- name: .jstestfuzz .common
+ - name: libunwind_tests
- name: .logical_session_cache .one_sec
- name: .ocsp
- name: replica_sets_auth_gen
@@ -10274,6 +10285,7 @@ buildvariants:
- name: jsCore_txns_large_txns_format
- name: .jstestfuzz .common
- name: .logical_session_cache .one_sec
+ - name: libunwind_tests
- name: replica_sets_auth_gen
- name: replica_sets_jscore_passthrough
- name: .replica_sets .multi_oplog
@@ -10293,17 +10305,16 @@ buildvariants:
# This variant is to intentionally test uncommon features nightly
- <<: *enterprise-rhel-70-64-bit-template
name: enterprise-rhel-70-64-bit-kitchen-sink
- display_name: "~ Enterprise RHEL 7.0 (Dagger, libunwind)"
+ display_name: "~ Enterprise RHEL 7.0 (Dagger)"
expansions:
<<: *enterprise-rhel-70-64-bit-expansions-template
- compile_flags: --ssl --use-libunwind MONGO_DISTMOD=rhel70 -j$(grep -c ^processor /proc/cpuinfo) --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars
+ compile_flags: --ssl MONGO_DISTMOD=rhel70 -j$(grep -c ^processor /proc/cpuinfo) --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars
additional_targets: dagger # If this moves to another variant, update the compile_all task
tasks:
- name: compile_all_run_unittests_TG
distros:
- rhel70
- name: jsCore
- - name: libunwind_tests
- <<: *enterprise-rhel-70-64-bit-template
name: hot_backups-rhel-70-64-bit
@@ -10321,13 +10332,13 @@ buildvariants:
- name: noPassthrough_gen
- <<: *enterprise-rhel-70-64-bit-template
- name: enterprise-rhel-70-64-bit-libunwind
- display_name: "~ Enterprise RHEL 7.0 (libunwind)"
+ name: enterprise-rhel-70-64-bit-no-libunwind
+ display_name: "~ Enterprise RHEL 7.0 (no-libunwind)"
runs_on:
- rhel70
expansions:
<<: *enterprise-rhel-70-64-bit-expansions-template
- compile_flags: --ssl MONGO_DISTMOD=rhel70 --opt=on -j$(grep -c ^processor /proc/cpuinfo) --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars --use-libunwind
+ compile_flags: --ssl MONGO_DISTMOD=rhel70 --use-libunwind=off --opt=on -j$(grep -c ^processor /proc/cpuinfo) --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars
has_packages: false
mh_target: ""
# Override list of tasks to exclude package testing and publishing
@@ -10347,7 +10358,6 @@ buildvariants:
- name: jsCore_txns_large_txns_format
- name: .jstestfuzz .common
- name: .logical_session_cache .one_sec
- - name: libunwind_tests
- name: replica_sets_auth_gen
- name: replica_sets_jscore_passthrough
- name: .replica_sets .multi_oplog
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
index 9774ef7e7bd..db471f1d1a9 100644
--- a/src/mongo/SConscript
+++ b/src/mongo/SConscript
@@ -56,7 +56,7 @@ env.SConscript(
# it, and do not declare other libraries in this file.
baseEnv = env.Clone()
-if use_libunwind:
+if use_libunwind == True:
baseEnv.InjectThirdParty('unwind')
stacktrace_impl_cpp = [ File('util/stacktrace_${TARGET_OS_FAMILY}.cpp') ]
@@ -307,6 +307,7 @@ config_header_substs = (
('@mongo_config_ssl_provider@', 'MONGO_CONFIG_SSL_PROVIDER'),
('@mongo_config_usdt_enabled@', 'MONGO_CONFIG_USDT_ENABLED'),
('@mongo_config_usdt_provider@', 'MONGO_CONFIG_USDT_PROVIDER'),
+ ('@mongo_config_use_libunwind@', 'MONGO_CONFIG_USE_LIBUNWIND'),
('@mongo_config_wiredtiger_enabled@', 'MONGO_CONFIG_WIREDTIGER_ENABLED'),
)
diff --git a/src/mongo/config.h.in b/src/mongo/config.h.in
index c7a9e1f5fd9..54e7a14787d 100644
--- a/src/mongo/config.h.in
+++ b/src/mongo/config.h.in
@@ -89,5 +89,8 @@
// Set to which provider defines USDT
@mongo_config_usdt_provider@
+// Defined if using libunwind.
+@mongo_config_use_libunwind@
+
// Defined if WiredTiger storage engine is enabled
@mongo_config_wiredtiger_enabled@
diff --git a/src/mongo/util/signal_handlers.cpp b/src/mongo/util/signal_handlers.cpp
index 47582a9ae84..77a3bfa0025 100644
--- a/src/mongo/util/signal_handlers.cpp
+++ b/src/mongo/util/signal_handlers.cpp
@@ -190,7 +190,7 @@ struct LogRotationState {
void handleOneSignal(const SignalWaitResult& waited, LogRotationState* rotation) {
int sig = waited.sig;
log() << "got signal " << sig << " (" << strsignal(sig) << ")";
-#ifdef __linux__
+#if defined(__linux__)
const siginfo_t& si = waited.si;
switch (si.si_code) {
case SI_USER:
@@ -221,12 +221,18 @@ void handleOneSignal(const SignalWaitResult& waited, LogRotationState* rotation)
}
return;
}
-#if defined(MONGO_STACKTRACE_CAN_DUMP_ALL_THREADS)
+
+#if defined(MONGO_STACKTRACE_HAS_SIGNAL)
if (sig == stackTraceSignal()) {
+ // If there's a stackTraceSignal at all, catch it here so we don't die from it.
+ // Can dump all threads if we can, else silently ignore it.
+#if defined(MONGO_STACKTRACE_CAN_DUMP_ALL_THREADS)
printAllThreadStacks();
+#endif
return;
}
#endif
+
// interrupt/terminate signal
log() << "will terminate after current cmd ends";
exitCleanly(EXIT_CLEAN);
@@ -247,8 +253,8 @@ void signalProcessingThread(LogFileStatus rotate) {
for (int sig : kSignalProcessingThreadExclusives)
sigaddset(&waitSignals, sig);
-#if defined(MONGO_STACKTRACE_CAN_DUMP_ALL_THREADS)
- // On this thread, block the stackTraceSignal and rely on sigwaitinfo to deliver it.
+#if defined(MONGO_STACKTRACE_HAS_SIGNAL)
+ // On this thread, block the stackTraceSignal and rely on a signal wait to deliver it.
sigaddset(&waitSignals, stackTraceSignal());
#endif
@@ -297,6 +303,13 @@ void startSignalProcessingThread(LogFileStatus rotate) {
for (int sig : kSignalProcessingThreadExclusives)
sigaddset(&sigset, sig);
+#if defined(MONGO_STACKTRACE_HAS_SIGNAL) && !defined(MONGO_STACKTRACE_CAN_DUMP_ALL_THREADS)
+ // On a Unixlike build without the stacktrace behavior, we still want to handle SIGUSR2 to
+ // print a message, but it must only go to the signalProcessingThread, not on other threads.
+ // It's as if stackTraceSignal (e.g. SIGUSR2) is a member of kSignalProcessingThreadExclusives.
+ sigaddset(&sigset, stackTraceSignal());
+#endif
+
// Mask signals in the current (only) thread. All new threads will inherit this mask.
invariant(pthread_sigmask(SIG_SETMASK, &sigset, nullptr) == 0);
// Spawn a thread to capture the signals we just masked off.
diff --git a/src/mongo/util/signal_handlers_synchronous.cpp b/src/mongo/util/signal_handlers_synchronous.cpp
index 86b48d46a09..be2a2bd175f 100644
--- a/src/mongo/util/signal_handlers_synchronous.cpp
+++ b/src/mongo/util/signal_handlers_synchronous.cpp
@@ -361,12 +361,10 @@ void clearSignalMask() {
#endif
}
-#ifdef __linux__
-
+#if defined(MONGO_STACKTRACE_HAS_SIGNAL)
int stackTraceSignal() {
return SIGUSR2;
}
-
#endif
} // namespace mongo
diff --git a/src/mongo/util/signal_handlers_synchronous.h b/src/mongo/util/signal_handlers_synchronous.h
index 53a5ff1fe2d..ceb513c4600 100644
--- a/src/mongo/util/signal_handlers_synchronous.h
+++ b/src/mongo/util/signal_handlers_synchronous.h
@@ -57,7 +57,11 @@ void reportOutOfMemoryErrorAndExit();
*/
void clearSignalMask();
-#ifdef __linux__
+#if defined(__linux__) || defined(__APPLE__)
+#define MONGO_STACKTRACE_HAS_SIGNAL
+#endif
+
+#if defined(MONGO_STACKTRACE_HAS_SIGNAL)
/**
* Returns the signal used to initiate all-thread stack traces.
*/
diff --git a/src/mongo/util/stacktrace.h b/src/mongo/util/stacktrace.h
index 01a300a06a6..535199862c3 100644
--- a/src/mongo/util/stacktrace.h
+++ b/src/mongo/util/stacktrace.h
@@ -36,6 +36,7 @@
#include <string>
#include "mongo/base/string_data.h"
+#include "mongo/config.h"
/**
* All-thread backtrace is only implemented on Linux. Even on Linux, it's only AS-safe
@@ -45,7 +46,7 @@
* - markAsStackTraceProcessingThread
* - printAllThreadStacks
*/
-#if defined(__linux__) && defined(MONGO_USE_LIBUNWIND)
+#if defined(__linux__) && defined(MONGO_CONFIG_USE_LIBUNWIND)
#define MONGO_STACKTRACE_CAN_DUMP_ALL_THREADS
#endif
diff --git a/src/mongo/util/stacktrace_bm.cpp b/src/mongo/util/stacktrace_bm.cpp
index 8638e9de058..87dc3cba2b3 100644
--- a/src/mongo/util/stacktrace_bm.cpp
+++ b/src/mongo/util/stacktrace_bm.cpp
@@ -47,7 +47,7 @@
#include "mongo/util/decimal_counter.h"
#include "mongo/util/stacktrace.h"
-#if defined(MONGO_USE_LIBUNWIND)
+#if defined(MONGO_CONFIG_USE_LIBUNWIND)
#include <libunwind.h>
#endif
@@ -101,7 +101,7 @@ void BM_Print(benchmark::State& state) {
}
BENCHMARK(BM_Print)->Range(1, 100);
-#if defined(MONGO_USE_LIBUNWIND)
+#if defined(MONGO_CONFIG_USE_LIBUNWIND)
void BM_CursorSteps(benchmark::State& state) {
size_t items = 0;
RecursionParam param;
@@ -134,7 +134,7 @@ void BM_CursorSteps(benchmark::State& state) {
state.SetItemsProcessed(items);
}
BENCHMARK(BM_CursorSteps)->Range(1, 100);
-#endif // MONGO_USE_LIBUNWIND
+#endif // MONGO_CONFIG_USE_LIBUNWIND
} // namespace
diff --git a/src/mongo/util/stacktrace_posix.cpp b/src/mongo/util/stacktrace_posix.cpp
index ced0438ab10..5b9a409e8ab 100644
--- a/src/mongo/util/stacktrace_posix.cpp
+++ b/src/mongo/util/stacktrace_posix.cpp
@@ -55,7 +55,7 @@
#define MONGO_STACKTRACE_BACKEND_LIBUNWIND 1
#define MONGO_STACKTRACE_BACKEND_EXECINFO 2
-#if defined(MONGO_USE_LIBUNWIND)
+#if defined(MONGO_CONFIG_USE_LIBUNWIND)
#define MONGO_STACKTRACE_BACKEND MONGO_STACKTRACE_BACKEND_LIBUNWIND
#elif defined(MONGO_CONFIG_HAVE_EXECINFO_BACKTRACE)
#define MONGO_STACKTRACE_BACKEND MONGO_STACKTRACE_BACKEND_EXECINFO
diff --git a/src/mongo/util/stacktrace_test.cpp b/src/mongo/util/stacktrace_test.cpp
index 441c965de00..ad82d9aa607 100644
--- a/src/mongo/util/stacktrace_test.cpp
+++ b/src/mongo/util/stacktrace_test.cpp
@@ -848,7 +848,7 @@ TEST_F(PrintAllThreadStacksTest, Go_200_Threads) {
#endif // defined(MONGO_STACKTRACE_CAN_DUMP_ALL_THREADS)
-#if defined(MONGO_USE_LIBUNWIND) || defined(MONGO_CONFIG_HAVE_EXECINFO_BACKTRACE)
+#if defined(MONGO_CONFIG_USE_LIBUNWIND) || defined(MONGO_CONFIG_HAVE_EXECINFO_BACKTRACE)
/**
* Try to backtrace from a stack containing a libc function. To do this
* we need a libc function that makes a user-provided callback, like qsort.
diff --git a/src/mongo/util/tcmalloc_parameters.idl b/src/mongo/util/tcmalloc_parameters.idl
index 15993865720..70586cda5e3 100644
--- a/src/mongo/util/tcmalloc_parameters.idl
+++ b/src/mongo/util/tcmalloc_parameters.idl
@@ -54,7 +54,7 @@ server_parameters:
cpp_varname: HeapProfilingEnabled
default: false
condition:
- preprocessor: defined(_POSIX_VERSION) && (defined(MONGO_CONFIG_HAVE_EXECINFO_BACKTRACE) || defined(MONGO_USE_LIBUNWIND))
+ preprocessor: defined(_POSIX_VERSION) && (defined(MONGO_CONFIG_HAVE_EXECINFO_BACKTRACE) || defined(MONGO_CONFIG_USE_LIBUNWIND))
heapProfilingSampleIntervalBytes:
description: "Configure heap profiling sample interval bytes"
@@ -64,7 +64,7 @@ server_parameters:
# 256kb
default: 262144
condition:
- preprocessor: defined(_POSIX_VERSION) && (defined(MONGO_CONFIG_HAVE_EXECINFO_BACKTRACE) || defined(MONGO_USE_LIBUNWIND))
+ preprocessor: defined(_POSIX_VERSION) && (defined(MONGO_CONFIG_HAVE_EXECINFO_BACKTRACE) || defined(MONGO_CONFIG_USE_LIBUNWIND))
tcmallocEnableMarkThreadTemporarilyIdle:
description: 'REMOVED: Setting this parameter has no effect and it will be removed in a future version of MongoDB.'
diff --git a/src/third_party/SConscript b/src/third_party/SConscript
index 840c1c96601..951e100b958 100644
--- a/src/third_party/SConscript
+++ b/src/third_party/SConscript
@@ -185,12 +185,12 @@ if not use_system_version_of_library('kms-message'):
if use_system_libunwind:
thirdPartyEnvironmentModifications['unwind'] = {
- 'CPPDEFINES' : ['MONGO_USE_LIBUNWIND', 'UNW_LOCAL_ONLY'],
+ 'CPPDEFINES' : ['UNW_LOCAL_ONLY'],
'SYSLIBDEPS' : [env['LIBDEPS_UNWIND_SYSLIBDEP'], 'lzma'],
}
elif use_vendored_libunwind:
thirdPartyEnvironmentModifications['unwind'] = {
- 'CPPDEFINES' : ['MONGO_USE_LIBUNWIND', 'UNW_LOCAL_ONLY'],
+ 'CPPDEFINES' : ['UNW_LOCAL_ONLY'],
'LIBDEPS' : ['$BUILD_DIR/third_party/shim_unwind'],
'SYSLIBDEPS' : ['lzma'],
}
diff --git a/src/third_party/unwind/SConscript b/src/third_party/unwind/SConscript
index 6b4ca0488ac..c425cdc2195 100644
--- a/src/third_party/unwind/SConscript
+++ b/src/third_party/unwind/SConscript
@@ -110,7 +110,7 @@ env.Append(
# propagates to consumers that Inject (depend on) unwind.
env.RegisterConsumerModifications(
CPPPATH=[unwind_platform.Dir("install/include")],
- CPPDEFINES=['UNW_LOCAL_ONLY', 'MONGO_USE_LIBUNWIND'],
+ CPPDEFINES=['UNW_LOCAL_ONLY'],
LIBS=['lzma'])
env.Append(