Threading and Clang

Hi,

We’re considering using Clang as a just in time compiler. It works great in a single thread, but we can’t get it working from multiple threads.

Here’s one attempt, where we create a single execution engine used by all threads, and one compiler instance per thread. The result is corruption and a core dump. We’ve also tried giving each thread its own execution engine, still no dice. This is with Clang/LLVM 2.7 on Ubuntu 9.10.

I’ve also attached a self contained zip file with the exact compile line and code that reproduces the problem.

Any idea what we’re doing wrong?

Thanks,

Martin

Here’s an example stack trace:

*** glibc detected *** ./boom: double free or corruption (fasttop): 0x00007fb9b421c9b0 ***

======= Backtrace: =========

/lib/libc.so.6[0x7fbabcf352f6]

/lib/libc.so.6(cfree+0x6c)[0x7fbabcf39c6c]

./boom(llvm::AttributeListImpl::DropRef()+0x3e)[0x18b4a4c]

./boom(llvm::AttrListPtr::operator=(llvm::AttrListPtr const&)+0x45)[0x18b3953]

./boom(llvm::Function::setAttributes(llvm::AttrListPtr const&)+0x24)[0xec2e1c]

./boom(llvm::Function::addAttribute(unsigned int, unsigned int)+0x5d)[0x19101e5]

./boom(llvm::Argument::addAttr(unsigned int)+0x32)[0x191094a]

./boom((anonymous namespace)::FunctionAttrs::AddNoCaptureAttrs(std::vector<llvm::CallGraphNode*, std::allocatorllvm::CallGraphNode* > const&)+0x131)[0x12e3f05]

./boom((anonymous namespace)::FunctionAttrs::runOnSCC(std::vector<llvm::CallGraphNode*, std::allocatorllvm::CallGraphNode* >&)+0x32)[0x12e464e]

./boom((anonymous namespace)::CGPassManager::RunPassOnSCC(llvm::Pass*, std::vector<llvm::CallGraphNode*, std::allocatorllvm::CallGraphNode* >&, llvm::CallGraph&, bool&)+0xa8)[0x17fafb4]

./boom((anonymous namespace)::CGPassManager::runOnModule(llvm::Module&)+0x24e)[0x17fb418]

./boom(llvm::MPPassManager::runOnModule(llvm::Module&)+0x17e)[0x194930c]

./boom(llvm::PassManagerImpl::run(llvm::Module&)+0x6f)[0x194b0b1]

./boom(llvm::PassManager::run(llvm::Module&)+0x21)[0x194b113]

./boom((anonymous namespace)::BackendConsumer::EmitAssembly()+0x241)[0xdfc3f9]

./boom((anonymous namespace)::BackendConsumer::HandleTranslationUnit(clang::ASTContext&)+0x91)[0xdffcef]

./boom(clang::ParseAST(clang::Preprocessor&, clang::ASTConsumer*, clang::ASTContext&, bool, bool, clang::CodeCompleteConsumer*)+0x2a4)[0xfc7164]

./boom(clang::ASTFrontendAction::ExecuteAction()+0x100)[0xe177a2]

./boom(clang::FrontendAction::Execute()+0xe2)[0xe17892]

./boom(clang::CompilerInstance::ExecuteAction(clang::FrontendAction&)+0x2a3)[0xe01427]

./boom(go(void*)+0x25f)[0xdf64f3]

/lib/libpthread.so.0[0x7fbabd9e0a04]

/lib/libc.so.6(clone+0x6d)[0x7fbabcf9ed4d]

test.cpp (3.29 KB)

boom.tgz (4.94 KB)

Hi,

We’re considering using Clang as a just in time compiler. It works great in a single thread, but we can’t get it working from multiple threads.

Here’s one attempt, where we create a single execution engine used by all threads, and one compiler instance per thread. The result is corruption and a core dump. We’ve also tried giving each thread its own execution engine, still no dice. This is with Clang/LLVM 2.7 on Ubuntu 9.10.

I'm not sure, but I'd strongly recommend upgrading to llvm 2.8 prerelease.

-Chris

Hi Chris,

I checked out the lastest LLVM and Clang from trunk last night. It still crashes, here’s the backtrace. Any other ideas? Is the way we’re using it supposed to work? If it is, we can dig in and see what’s going wrong.

Bes,

Martin

*** glibc detected *** ./boom: double free or corruption (fasttop): 0x0000000004136370 ***

======= Backtrace: =========

/lib/libc.so.6[0x7fc2fe7a92f6]

/lib/libc.so.6(cfree+0x6c)[0x7fc2fe7adc6c]

./boom(__gnu_cxx::new_allocatorllvm::PassRegistrationListener*::deallocate(llvm::PassRegistrationListener**, unsigned long)+0x1d)[0x1c24c85]

./boom(std::_Vector_base<llvm::PassRegistrationListener*, std::allocatorllvm::PassRegistrationListener* >::_M_deallocate(llvm::PassRegistrationListener**, unsigned long)+0x2f)[0x1c24cb7]

./boom(std::vector<llvm::PassRegistrationListener*, std::allocatorllvm::PassRegistrationListener* >::_M_insert_aux(__gnu_cxx::__normal_iterator<llvm::PassRegistrationListener**, std::vector<llvm::PassRegistrationListener*, std::allocatorllvm::PassRegistrationListener* > >, llvm::PassRegistrationListener* const&)+0x310)[0x1c24fca]

./boom(std::vector<llvm::PassRegistrationListener*, std::allocatorllvm::PassRegistrationListener* >::push_back(llvm::PassRegistrationListener* const&)+0x6c)[0x1c25098]

./boom(llvm::PassRegistry::addRegistrationListener(llvm::PassRegistrationListener*)+0x2e)[0x1c22f90]

./boom(llvm::PassRegistrationListener::PassRegistrationListener()+0x2f)[0x1c12163]

./boom((anonymous namespace)::GetCFGOnlyPasses::GetCFGOnlyPasses(llvm::SmallVector<void const*, 32u>&)+0x19)[0x1c132b5]

./boom(llvm::AnalysisUsage::setPreservesCFG()+0x20)[0x1c12186]

./boom((anonymous namespace)::SROA::getAnalysisUsage(llvm::AnalysisUsage&) const+0x2b)[0x1a0b78d]

./boom(llvm::PMTopLevelManager::findAnalysisUsage(llvm::Pass*)+0xa7)[0x1c14917]

./boom(llvm::PMTopLevelManager::schedulePass(llvm::Pass*)+0xd7)[0x1c15e3b]

./boom(llvm::FunctionPassManagerImpl::add(llvm::Pass*)+0x24)[0x1c22398]

./boom(llvm::FunctionPassManager::addImpl(llvm::Pass*)+0x21)[0x1c1638d]

./boom(llvm::FunctionPassManager::add(llvm::Pass*)+0x12c)[0x1c164bc]

./boom[0x107e70b]

./boom((anonymous namespace)::EmitAssemblyHelper::CreatePasses()+0xaf)[0x107ed0f]

./boom((anonymous namespace)::EmitAssemblyHelper::EmitAssembly(clang::BackendAction, llvm::raw_ostream*)+0x77)[0x107ee83]

./boom(clang::EmitBackendOutput(clang::Diagnostic&, clang::CodeGenOptions const&, clang::TargetOptions const&, llvm::Module*, clang::BackendAction, llvm::raw_ostream*)+0x73)[0x107f255]

./boom((anonymous namespace)::BackendConsumer::HandleTranslationUnit(clang::ASTContext&)+0x189)[0x107ce91]

./boom(clang::ParseAST(clang::Sema&, bool)+0x216)[0x11bc388]

./boom(clang::ASTFrontendAction::ExecuteAction()+0xea)[0xf4e370]

./boom(clang::CodeGenAction::ExecuteAction()+0x352)[0x107b87c]

./boom(clang::FrontendAction::Execute()+0x100)[0xf4e478]

./boom(clang::CompilerInstance::ExecuteAction(clang::FrontendAction&)+0x294)[0xf35414]

./boom(go(void*)+0x25f)[0xf2ff93]

/lib/libpthread.so.0[0x7fc2ff458a04]

/lib/libc.so.6(clone+0x6d)[0x7fc2fe812d4d]

Has this issue been resolved, and if so what was the culprit?

Thanks in advance

Garrison

Hi Chris,

I checked out the lastest LLVM and Clang from trunk last night. It still crashes, here’s the backtrace. Any other ideas? Is the way we’re using it supposed to work? If it is, we can dig in and see what’s going wrong.

Bes,
Martin

*** glibc detected *** ./boom: double free or corruption (fasttop): 0x0000000004136370 ***
======= Backtrace: =========
/lib/libc.so.6[0x7fc2fe7a92f6]

[snip]

From: Chris Lattner [mailto:clattner@apple.com]
Sent: Monday, September 13, 2010 6:43 PM
To: Martin C. Martin
Cc: Clang Dev; Owen Anderson
Subject: Re: [cfe-dev] Threading and Clang

Hi,

We’re considering using Clang as a just in time compiler. It works great in a single thread, but we can’t get it working from multiple threads.

Here’s one attempt, where we create a single execution engine used by all threads, and one compiler instance per thread. The result is corruption and a core dump. We’ve also tried giving each thread its own execution engine, still no dice. This is with Clang/LLVM 2.7 on Ubuntu 9.10.

I'm not sure, but I'd strongly recommend upgrading to llvm 2.8 prerelease.

-Chris

I’ve also attached a self contained zip file with the exact compile line and code that reproduces the problem.

Any idea what we’re doing wrong?

Thanks,
Martin

Here’s an example stack trace:

*** glibc detected *** ./boom: double free or corruption (fasttop): 0x00007fb9b421c9b0 ***
======= Backtrace: =========
/lib/libc.so.6[0x7fbabcf352f6]

[snip]