FIRE-17517; LD_PRELOAD libcef.so when launching a plugin that will dso-load media_plugin_cef. Reasoning is that libcef.so is bild with tcmalloc and thus will cause all kind of havok if not preloaded. Hopefully cefbuilds will stop doing this soon enough (see https://bitbucket.org/chromiumembedded/cef/issues/1827) and this can be reverted.

Alternative is to rebuild CEF each and every time for x86 and x64 when it is updated.

See also:
http://jira.phoenixviewer.com/browse/FIRE-17517
https://lists.secondlife.com/pipermail/opensource-dev/2015-July/010106.html
https://bitbucket.org/chromiumembedded/cef/issues/1827/tcmalloc-should-be-disabled-in-linux-osx
master
Nicky 2016-02-07 23:47:58 +01:00
parent 9811fbc14f
commit 2700f7994e
4 changed files with 58 additions and 0 deletions

View File

@ -507,6 +507,40 @@ LLProcessPtr LLProcess::create(const LLSDOrParams& params)
}
}
// <FS:ND> Annoying preload hack to make tcmalloc in libcef.so play nicely.
std::string installPreloadHack( std::string const &preload )
{
std::string strOldPreload;
#ifdef LL_LINUX
if( preload.size() )
{
std::string strPreload = preload;
if( getenv( "LD_PRELOAD" ) )
{
strOldPreload = getenv( "PRELOAD" );
strPreload = ":" + strOldPreload;
}
setenv( "LD_PRELOAD", strPreload.c_str(), 1 );
}
#endif
return strOldPreload;
}
void uninstallPreloadHack( std::string const &preload, std::string const &strOldPreload )
{
#ifdef LL_LINUX
if( preload.empty() )
return;
if( strOldPreload.size() )
setenv( "LD_PRELOAD", strOldPreload.c_str(), 1 );
else
unsetenv( "LD_PRELOAD" );
#endif
}
// </FS:ND>
/// Call an apr function returning apr_status_t. On failure, log warning and
/// throw LLProcessError mentioning the function call that produced that
/// result.
@ -672,15 +706,20 @@ LLProcess::LLProcess(const LLSDOrParams& params):
// terminate with a null pointer
argv.push_back(NULL);
std::string strOldPreload = installPreloadHack( params.preload ); // FS:ND/> Install preload hack (if needed)
// Launch! The NULL would be the environment block, if we were passing
// one. Hand-expand chkapr() macro so we can fill in the actual command
// string instead of the variable names.
if (ll_apr_warn_status(apr_proc_create(&mProcess, argv[0], &argv[0], NULL, procattr,
gAPRPoolp)))
{
uninstallPreloadHack( params.preload, strOldPreload ); // <FS:ND/> Remove preload hack
throw LLProcessError(STRINGIZE(params << " failed"));
}
uninstallPreloadHack( params.preload, strOldPreload ); // <FS:ND/> Remove preload hack
// arrange to call status_callback()
apr_proc_other_child_register(&mProcess, &LLProcess::status_callback, this, mProcess.in,
gAPRPoolp);

View File

@ -227,6 +227,15 @@ public:
* executable name.
*/
Optional<std::string> desc;
/**
<FS:ND> HACK! libcef.so bleeds that intrusive tcmalloc hacks all over the process.
This then causes awesome effects like crashes and memory corruption when the so is loaded dynamically.
We uses this argument to force libcef.so be preloaded, which fixes this.
The other solution would be to recompile CEF twice (x86/x64) for each CEF update. Which I really would like to avoid.
*/
Optional<std::string> preload;
};
typedef LLSDParamAdapter<Params> LLSDOrParams;

View File

@ -480,6 +480,14 @@ void LLPluginProcessParent::idle(void)
// Only argument to the launcher is the port number we're listening on
mProcessParams.args.add(stringize(mBoundPort));
#if LL_LINUX
if( mPluginFile.find( "cef" ) != std::string::npos && getenv( "FS_CEF_PRELOAD" ) )
{
mProcessParams.preload = getenv( "FS_CEF_PRELOAD" );
LL_INFOS( "Plugin" ) << "Forcing LD_PRELOAD for " << (std::string)mProcessParams.executable << " with a value of " << (std::string)mProcessParams.preload << LL_ENDL;
}
#endif
if (! (mProcess = LLProcess::create(mProcessParams)))
{
errorState();

View File

@ -162,6 +162,8 @@ fi
fi
export FS_CEF_PRELOAD="`pwd`/lib/libcef.so"
# Copy "$@" to ARGS array specifically to delete the --skip-gridargs switch.
# The gridargs.dat file is no more, but we still want to avoid breaking
# scripts that invoke this one with --skip-gridargs.