0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 17:10:48 +01:00

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.
This commit is contained in:
Tad Marshall 2013-06-20 11:53:23 -04:00
parent 38d638004c
commit 54f25e6292
8 changed files with 194 additions and 64 deletions

View File

@ -1224,7 +1224,8 @@ def doConfigure(myenv):
if (conf.CheckCXXHeader( "execinfo.h" ) and
conf.CheckDeclaration('backtrace', includes='#include <execinfo.h>') and
conf.CheckDeclaration('backtrace_symbols', includes='#include <execinfo.h>')):
conf.CheckDeclaration('backtrace_symbols', includes='#include <execinfo.h>') and
conf.CheckDeclaration('backtrace_symbols_fd', includes='#include <execinfo.h>')):
conf.env.Append( CPPDEFINES=[ "MONGO_HAVE_EXECINFO_BACKTRACE" ] )

View File

@ -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',

View File

@ -3,6 +3,7 @@
Import("env")
env.Library('platform', [
'backtrace.cpp',
'posix_fadvise.cpp',
'process_id.cpp',
'random.cpp',

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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