diff options
author | Tad Marshall <tad@10gen.com> | 2013-06-20 11:53:23 -0400 |
---|---|---|
committer | Tad Marshall <tad@10gen.com> | 2013-06-20 11:53:23 -0400 |
commit | 54f25e6292eb565d4eadec1d5d75d286c787c053 (patch) | |
tree | 8e80d223d28492552a7416092659330fa379f3ad /src | |
parent | 38d638004c0125a52e4dc86b586efec3e2efee4c (diff) | |
download | mongo-54f25e6292eb565d4eadec1d5d75d286c787c053.tar.gz |
SERVER-7080 Link to backtrace, backtrace_symbols and backtrace_symbols_fd at runtime
Do not make direct calls to backtrace, backtrace_symbols or backtrace_symbols_fd,
which are present in Solaris 11 but not in Solaris 10. Instead, see if they are
available in a loaded library (which will be libc.so.1) at runtime and either
call them or call an emulation.
Diffstat (limited to 'src')
-rw-r--r-- | src/SConscript.client | 1 | ||||
-rw-r--r-- | src/mongo/platform/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/platform/backtrace.cpp | 93 | ||||
-rw-r--r-- | src/mongo/platform/backtrace.h | 43 | ||||
-rw-r--r-- | src/mongo/util/signal_handlers.cpp | 17 | ||||
-rw-r--r-- | src/mongo/util/stack_introspect.cpp | 18 | ||||
-rw-r--r-- | src/mongo/util/stacktrace.cpp | 82 |
7 files changed, 192 insertions, 63 deletions
diff --git a/src/SConscript.client b/src/SConscript.client index 7f543723b1b..9abcfadbae7 100644 --- a/src/SConscript.client +++ b/src/SConscript.client @@ -51,6 +51,7 @@ clientSourceBasic = [ 'mongo/db/namespace.cpp', 'mongo/db/dbmessage.cpp', 'mongo/pch.cpp', + 'mongo/platform/backtrace.cpp', 'mongo/platform/posix_fadvise.cpp', 'mongo/platform/process_id.cpp', 'mongo/platform/random.cpp', diff --git a/src/mongo/platform/SConscript b/src/mongo/platform/SConscript index 4a81a31d9cb..078e9798680 100644 --- a/src/mongo/platform/SConscript +++ b/src/mongo/platform/SConscript @@ -3,6 +3,7 @@ Import("env") env.Library('platform', [ + 'backtrace.cpp', 'posix_fadvise.cpp', 'process_id.cpp', 'random.cpp', diff --git a/src/mongo/platform/backtrace.cpp b/src/mongo/platform/backtrace.cpp new file mode 100644 index 00000000000..9bb3fd0283c --- /dev/null +++ b/src/mongo/platform/backtrace.cpp @@ -0,0 +1,93 @@ +/* Copyright 2013 10gen Inc. + * + * 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. + */ + +#if !defined(_WIN32) +#if defined(__sunos__) || !defined(MONGO_HAVE_EXECINFO_BACKTRACE) + +#include "mongo/platform/backtrace.h" + +#include <dlfcn.h> + +#include "mongo/base/init.h" +#include "mongo/base/status.h" + +namespace mongo { +namespace pal { + + int backtrace_emulation(void** array, int size) { + return 0; + } + + char** backtrace_symbols_emulation(void* const* array, int size) { + return NULL; + } + + void backtrace_symbols_fd_emulation(void* const* array, int size, int fd) { + } + + typedef int (*BacktraceFunc)(void** array, int size); + static BacktraceFunc backtrace_switcher = + pal::backtrace_emulation; + + typedef char** (*BacktraceSymbolsFunc)(void* const* array, int size); + static BacktraceSymbolsFunc backtrace_symbols_switcher = + pal::backtrace_symbols_emulation; + + typedef void (*BacktraceSymbolsFdFunc)(void* const* array, int size, int fd); + static BacktraceSymbolsFdFunc backtrace_symbols_fd_switcher = + pal::backtrace_symbols_fd_emulation; + + int backtrace(void** array, int size) { + return backtrace_switcher(array, size); + } + + char** backtrace_symbols(void* const* array, int size) { + return backtrace_symbols_switcher(array, size); + } + + void backtrace_symbols_fd(void* const* array, int size, int fd) { + backtrace_symbols_fd_switcher(array, size, fd); + } + +} // namespace pal + + // 'backtrace()', 'backtrace_symbols()' and 'backtrace_symbols_fd()' on Solaris will call + // emulation functions if the symbols are not found + // + MONGO_INITIALIZER_GENERAL(SolarisBacktrace, + MONGO_NO_PREREQUISITES, + ("default"))(InitializerContext* context) { + void* functionAddress = dlsym(RTLD_DEFAULT, "backtrace"); + if (functionAddress != NULL) { + pal::backtrace_switcher = + reinterpret_cast<pal::BacktraceFunc>(functionAddress); + } + functionAddress = dlsym(RTLD_DEFAULT, "backtrace_symbols"); + if (functionAddress != NULL) { + pal::backtrace_symbols_switcher = + reinterpret_cast<pal::BacktraceSymbolsFunc>(functionAddress); + } + functionAddress = dlsym(RTLD_DEFAULT, "backtrace_symbols_fd"); + if (functionAddress != NULL) { + pal::backtrace_symbols_fd_switcher = + reinterpret_cast<pal::BacktraceSymbolsFdFunc>(functionAddress); + } + return Status::OK(); + } + +} // namespace mongo + +#endif // #if defined(__sunos__) +#endif // #if !defined(_WIN32) diff --git a/src/mongo/platform/backtrace.h b/src/mongo/platform/backtrace.h new file mode 100644 index 00000000000..962cfa43119 --- /dev/null +++ b/src/mongo/platform/backtrace.h @@ -0,0 +1,43 @@ +/* Copyright 2013 10gen Inc. + * + * 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. + */ + +#pragma once + +#if !defined(_WIN32) +#if defined(__sunos__) || !defined(MONGO_HAVE_EXECINFO_BACKTRACE) + +namespace mongo { + namespace pal { + int backtrace(void** array, int size); + char** backtrace_symbols(void* const* array, int size); + void backtrace_symbols_fd(void* const* array, int size, int fd); + } // namespace pal + using pal::backtrace; + using pal::backtrace_symbols; + using pal::backtrace_symbols_fd; +} // namespace mongo + +#else + +#include <execinfo.h> + +namespace mongo { + using ::backtrace; + using ::backtrace_symbols; + using ::backtrace_symbols_fd; +} // namespace mongo + +#endif +#endif diff --git a/src/mongo/util/signal_handlers.cpp b/src/mongo/util/signal_handlers.cpp index 52694900448..241d824b1a0 100644 --- a/src/mongo/util/signal_handlers.cpp +++ b/src/mongo/util/signal_handlers.cpp @@ -16,7 +16,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "pch.h" +#include "mongo/pch.h" #include <cstdarg> #include <cstdio> @@ -26,20 +26,17 @@ #include <unistd.h> #endif -#ifdef MONGO_HAVE_EXECINFO_BACKTRACE -#include <execinfo.h> -#endif - -#include "log.h" -#include "signal_handlers.h" +#include "mongo/platform/backtrace.h" +#include "mongo/util/log.h" +#include "mongo/util/signal_handlers.h" namespace mongo { /* * WARNING: PLEASE READ BEFORE CHANGING THIS MODULE * - * All code in this module should be singal-friendly. Before adding any system - * call or other dependency, please make sure the latter still holds. + * All code in this module must be signal-friendly. Before adding any system + * call or other dependency, please make sure that this still holds. * */ @@ -84,7 +81,7 @@ namespace mongo { static void formattedBacktrace( int fd ) { -#ifdef MONGO_HAVE_EXECINFO_BACKTRACE +#if !defined(_WIN32) int numFrames; const int MAX_DEPTH = 20; diff --git a/src/mongo/util/stack_introspect.cpp b/src/mongo/util/stack_introspect.cpp index 67208bf3fde..eec8c1efbc5 100644 --- a/src/mongo/util/stack_introspect.cpp +++ b/src/mongo/util/stack_introspect.cpp @@ -18,22 +18,21 @@ #include "mongo/util/stack_introspect.h" +#if !defined(_WIN32) + #include <cstdlib> +#include <cxxabi.h> #include <iostream> -#include <string> #include <map> +#include <string> #include <vector> +#include "mongo/platform/backtrace.h" #include "mongo/util/concurrency/mutex.h" #include "mongo/util/text.h" using namespace std; -#ifdef MONGO_HAVE_EXECINFO_BACKTRACE - -#include <execinfo.h> -#include <cxxabi.h> - namespace mongo { namespace { @@ -111,7 +110,7 @@ namespace mongo { bool inConstructorChain( bool printOffending ){ void* b[maxBackTraceFrames]; - int size = ::backtrace( b, maxBackTraceFrames ); + int size = backtrace( b, maxBackTraceFrames ); char** strings = 0; @@ -127,7 +126,7 @@ namespace mongo { } if ( ! strings ) - strings = ::backtrace_symbols( b, size ); + strings = backtrace_symbols( b, size ); string symbol = strings[i]; @@ -181,5 +180,4 @@ namespace mongo { bool inConstructorChainSupported() { return false; } } -#endif // defined(MONGO_HAVE_EXECINFO_BACKTRACE) - +#endif // #if !defined(_WIN32) diff --git a/src/mongo/util/stacktrace.cpp b/src/mongo/util/stacktrace.cpp index ef0015174e3..c1348a00240 100644 --- a/src/mongo/util/stacktrace.cpp +++ b/src/mongo/util/stacktrace.cpp @@ -24,53 +24,18 @@ #include "mongo/util/log.h" #ifdef _WIN32 -#include <sstream> -#include <stdio.h> #include <boost/filesystem/operations.hpp> #include <boost/smart_ptr/scoped_array.hpp> +#include <sstream> +#include <stdio.h> #include "mongo/platform/windows_basic.h" #include <DbgHelp.h> #include "mongo/util/assert_util.h" +#else +#include "mongo/platform/backtrace.h" #endif -#ifdef MONGO_HAVE_EXECINFO_BACKTRACE - -#include <execinfo.h> - -namespace mongo { - static const int maxBackTraceFrames = 20; - - /** - * Print a stack backtrace for the current thread to the specified ostream. - * - * @param os ostream& to receive printed stack backtrace - */ - void printStackTrace( std::ostream& os ) { - - void *b[maxBackTraceFrames]; - - int size = ::backtrace( b, maxBackTraceFrames ); - for ( int i = 0; i < size; i++ ) - os << std::hex << b[i] << std::dec << ' '; - os << std::endl; - - char **strings; - - strings = ::backtrace_symbols( b, size ); - if (strings == NULL) { - const int err = errno; - os << "Unable to collect backtrace symbols (" << errnoWithDescription(err) << ")" - << std::endl; - return; - } - for ( int i = 0; i < size; i++ ) - os << ' ' << strings[i] << '\n'; - os.flush(); - ::free( strings ); - } -} - -#elif defined(_WIN32) +#if defined(_WIN32) namespace mongo { @@ -319,12 +284,43 @@ namespace mongo { } } - #else namespace mongo { - void printStackTrace( std::ostream &os ) {} + static const int maxBackTraceFrames = 20; + + /** + * Print a stack backtrace for the current thread to the specified ostream. + * + * @param os ostream& to receive printed stack backtrace + */ + void printStackTrace( std::ostream& os ) { + + void* addresses[maxBackTraceFrames]; + + int addressCount = backtrace(addresses, maxBackTraceFrames); + if (addressCount == 0) { + const int err = errno; + os << "Unable to collect backtrace addresses (" << errnoWithDescription(err) << ")" + << std::endl; + return; + } + for (int i = 0; i < addressCount; i++) + os << std::hex << addresses[i] << std::dec << ' '; + os << std::endl; + + char** backtraceStrings = backtrace_symbols(addresses, addressCount); + if (backtraceStrings == NULL) { + const int err = errno; + os << "Unable to collect backtrace symbols (" << errnoWithDescription(err) << ")" + << std::endl; + return; + } + for (int i = 0; i < addressCount; i++) + os << ' ' << backtraceStrings[i] << '\n'; + os.flush(); + free(backtraceStrings); + } } #endif - |