diff --git a/SConstruct b/SConstruct index c8217f1479f..9b97b705b30 100644 --- a/SConstruct +++ b/SConstruct @@ -1405,15 +1405,6 @@ if use_libunwind == True: if env.TargetOSIs('windows') and link_model not in ['object', 'static', 'dynamic-sdk']: env.FatalError("Windows builds must use the 'object', 'dynamic-sdk', or 'static' link models") - -# The mongodbtoolchain currently doesn't produce working binaries if -# you combine a dynamic build with a non-system allocator, but the -# failure mode is non-obvious. For now, prevent people from wandering -# inadvertantly into this trap. Remove this constraint when -# https://jira.mongodb.org/browse/SERVER-27675 is resolved. -if (link_model == 'dynamic') and ('mongodbtoolchain' in env['CXX']) and (env['MONGO_ALLOCATOR'] != 'system'): - env.FatalError('Cannot combine the MongoDB toolchain, a dynamic build, and a non-system allocator. Choose two.') - # The 'object' mode for libdeps is enabled by setting _LIBDEPS to $_LIBDEPS_OBJS. The other two # modes operate in library mode, enabled by setting _LIBDEPS to $_LIBDEPS_LIBS. env['_LIBDEPS'] = '$_LIBDEPS_OBJS' if link_model == "object" else '$_LIBDEPS_LIBS' diff --git a/src/third_party/SConscript b/src/third_party/SConscript index 20150aea4b5..9e80376fb15 100644 --- a/src/third_party/SConscript +++ b/src/third_party/SConscript @@ -1,5 +1,7 @@ # -*- mode: python -*- +import SCons + import libdeps import json @@ -208,6 +210,42 @@ def injectThirdParty(thisEnv, libraries=[], parts=[]): env.AddMethod(injectThirdParty, 'InjectThirdParty') +# In a dynamic build, force everything to depend on shim_allocator, so +# that it topsorts to the end of the list. We are totally relying on +# the fact that we are altering the env from src/SConscript +if get_option('link-model').startswith("dynamic"): + + for builder_name in ('Program', 'SharedLibrary', 'LoadableModule', 'StaticLibrary'): + builder = env['BUILDERS'][builder_name] + base_emitter = builder.emitter + + def add_shim_allocator_hack(target, source, env): + + # If we allowed conftests to become dependent, any TryLink + # that happened after we made the below modifications would + # cause the configure steps to try to compile tcmalloc and any + # of its dependencies. Oops! + if any('conftest' in str(t) for t in target): + return target, source + + # It is possible that 'env' isn't a unique + # OverrideEnvironment, since if you didn't pass any kw args + # into your builder call, you just reuse the env you were + # called with. That could mean that we see the same + # envirnoment here multiple times. But that is really OK, + # since the operation we are performing would be performed on + # all of them anyway. The flag serves as a way to disable the + # auto-injection for the handful of libraries where we must do + # so to avoid forming a cycle. + if not env.get('DISABLE_ALLOCATOR_SHIM_INJECTION', False): + lds = env.get('LIBDEPS', []) + lds.append('$BUILD_DIR/third_party/shim_allocator') + env['LIBDEPS'] = lds + + return target, source + + builder.emitter = SCons.Builder.ListEmitter([add_shim_allocator_hack, base_emitter]) + env = env.Clone() murmurEnv = env.Clone() @@ -249,7 +287,12 @@ if use_libunwind: target="shim_unwind", source=[ 'shim_unwind.cpp', - ]) + ], + # We don't want the shim_allocator hack to apply to this library, since + # otherwise we would create a loop, since tcmalloc might use us. That should + # be OK, unless libunwind had static initializers that invoked malloc. + DISABLE_ALLOCATOR_SHIM_INJECTION=True, + ) if use_system_version_of_library("fmt"): fmtEnv = env.Clone( @@ -493,7 +536,9 @@ gperftoolsEnv.Library( target="shim_allocator", source=[ "shim_allocator.cpp", - ]) + ], + DISABLE_ALLOCATOR_SHIM_INJECTION=True, +) if use_system_version_of_library("stemmer"): diff --git a/src/third_party/gperftools-2.7/SConscript b/src/third_party/gperftools-2.7/SConscript index 8fcdab56fdb..55c063ebbd0 100644 --- a/src/third_party/gperftools-2.7/SConscript +++ b/src/third_party/gperftools-2.7/SConscript @@ -115,5 +115,8 @@ env.Library( LIBDEPS=[ '$BUILD_DIR/third_party/shim_unwind' if use_libunwind else [], - ] + ], + # We don't want the shim_allocator hack to apply to this library, since + # otherwise we would create a loop. + DISABLE_ALLOCATOR_SHIM_INJECTION=True, ) diff --git a/src/third_party/unwind/SConscript b/src/third_party/unwind/SConscript index 7a6d6344fc8..ed947c8e8e8 100644 --- a/src/third_party/unwind/SConscript +++ b/src/third_party/unwind/SConscript @@ -123,4 +123,9 @@ env.Append( env.Library( target='unwind', - source=env.File(unwind_sources, unwind_src_dir)) + source=env.File(unwind_sources, unwind_src_dir), + # We don't want the shim_allocator hack to apply to this library, since + # otherwise we would create a loop, since tcmalloc might use us. That should + # be OK, unless libunwind had static initializers that invoked malloc. + DISABLE_ALLOCATOR_SHIM_INJECTION=True, +)