summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTad Marshall <tad@10gen.com>2013-06-20 11:53:23 -0400
committerTad Marshall <tad@10gen.com>2013-06-20 11:53:23 -0400
commit54f25e6292eb565d4eadec1d5d75d286c787c053 (patch)
tree8e80d223d28492552a7416092659330fa379f3ad /src
parent38d638004c0125a52e4dc86b586efec3e2efee4c (diff)
downloadmongo-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.client1
-rw-r--r--src/mongo/platform/SConscript1
-rw-r--r--src/mongo/platform/backtrace.cpp93
-rw-r--r--src/mongo/platform/backtrace.h43
-rw-r--r--src/mongo/util/signal_handlers.cpp17
-rw-r--r--src/mongo/util/stack_introspect.cpp18
-rw-r--r--src/mongo/util/stacktrace.cpp82
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
-