Skip to content

Commit

Permalink
SERVER-15710 Add better leak sanitizer integration
Browse files Browse the repository at this point in the history
  • Loading branch information
acmorrow committed Oct 29, 2014
1 parent 73f4e5d commit 981b06c
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 7 deletions.
38 changes: 32 additions & 6 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -1552,7 +1552,9 @@ def doConfigure(myenv):

sanitizer_list = get_option('sanitize').split(',')

using_asan = 'address' in sanitizer_list or 'leak' in sanitizer_list
using_lsan = 'leak' in sanitizer_list
using_asan = 'address' in sanitizer_list or using_lsan

if using_asan:
if get_option('allocator') == 'tcmalloc':
print("Cannot use address or leak sanitizer with tcmalloc")
Expand All @@ -1566,8 +1568,10 @@ def doConfigure(myenv):
# --sanitize=address,leak: -fsanitize=address, detect_leaks=1
# --sanitize=address: -fsanitize=address
#
if 'leak' in sanitizer_list:
myenv['ENV']['ASAN_OPTIONS'] = "detect_leaks=1"
if using_lsan:
if using_asan:
myenv['ENV']['ASAN_OPTIONS'] = "detect_leaks=1"
myenv['ENV']['LSAN_OPTIONS'] = "suppressions=%s" % myenv.File("#etc/lsan.suppressions").abspath
if 'address' in sanitizer_list:
sanitizer_list.remove('leak')

Expand All @@ -1580,12 +1584,34 @@ def doConfigure(myenv):
print( 'Failed to enable sanitizers with flag: ' + sanitizer_option )
Exit(1)

blackfiles_map = {
"address" : myenv.File("#etc/asan.blacklist"),
"leak" : myenv.File("#etc/asan.blacklist"),
"thread" : myenv.File("#etc/tsan.blacklist"),
"undefined" : myenv.File("#etc/ubsan.blacklist"),
}

blackfiles = set([v for (k, v) in blackfiles_map.iteritems() if k in sanitizer_list])
blacklist_options=["-fsanitize-blacklist=%s" % blackfile for blackfile in blackfiles]

for blacklist_option in blacklist_options:
if AddToCCFLAGSIfSupported(myenv, blacklist_option):
myenv.Append(LINKFLAGS=[blacklist_option])

llvm_symbolizer = get_option('llvm-symbolizer')
if not os.path.isabs(llvm_symbolizer):
if os.path.isabs(llvm_symbolizer):
if not myenv.File(llvm_symbolizer).exists():
print("WARNING: Specified symbolizer '%s' not found" % llvm_symbolizer)
llvm_symbolizer = None
else:
llvm_symbolizer = myenv.WhereIs(llvm_symbolizer)

if llvm_symbolizer:
if using_asan:
myenv['ENV']['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
myenv['ENV']['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
myenv['ENV']['LSAN_SYMBOLIZER_PATH'] = llvm_symbolizer
elif using_lsan:
print("Using the leak sanitizer requires a valid symbolizer")
Exit(1)

# When using msvc,
# check for min version of VS2013 for fixes in std::list::splice
Expand Down
Empty file added etc/asan.blacklist
Empty file.
17 changes: 17 additions & 0 deletions etc/lsan.suppressions
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Client objects are leaked in threads that are never terminated
leak:mongo::Client::Client

# Insanity related to the fact that the static observer
# prevents deleting mutexes during clean shutdown. If you
# remove the StaticObserver, remove this too.
leak:mongo::mutex::mutex

# Thread names leak from threads that are never terminated.
leak:mongo::setThreadName

# lets just ignore v8 for now. If we upgrade to newer v8
# try removing this suppression
leak:v8::

# List1 is an abomination, as is its test.
leak:ThreadedTests::List1
Empty file added etc/tsan.blacklist
Empty file.
Empty file added etc/ubsan.blacklist
Empty file.
5 changes: 4 additions & 1 deletion src/mongo/util/concurrency/mutex.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <boost/thread/mutex.hpp>
#include <boost/thread/xtime.hpp>

#include "mongo/bson/inline_decls.h"
#include "mongo/util/assert_util.h"
#include "mongo/util/heapcheck.h"
#include "mongo/util/concurrency/threadlocal.h"
Expand Down Expand Up @@ -82,7 +83,9 @@ namespace mongo {
class mutex : boost::noncopyable {
public:
const char * const _name;
mutex(const char *name) : _name(name)
// NOINLINE so that 'mutex::mutex' is always in the frame, this makes
// it easier for us to suppress the leaks caused by the static observer.
NOINLINE_DECL mutex(const char *name) : _name(name)
{
_m = new boost::timed_mutex();
IGNORE_OBJECT( _m ); // Turn-off heap checking on _m
Expand Down

0 comments on commit 981b06c

Please sign in to comment.