Protect IncrementalExecutor::m_AtExitFuncs with a spin lock.

This prevents:

==4150== Possible data race during write of size 8 at 0xCC136F0 by thread #3
==4150== Locks held: none
==4150==    at 0x146EC214: llvm::SmallVectorTemplateBase<cling::IncrementalExecutor::CXAAtExitElement, false>::grow(unsigned long) (in /afs/cern.ch/cms/sw/ReleaseCandidates/volB/slc6_amd64_gcc491/lcg/root/6.02.00-lnjiaj2/lib/libCling.so)
==4150==    by 0x146E9DE3: cling::IncrementalExecutor::AddAtExitFunc(void (*)(void*), void*, cling::Transaction const*) (in /afs/cern.ch/cms/sw/ReleaseCandidates/volB/slc6_amd64_gcc491/lcg/root/6.02.00-lnjiaj2/lib/libCling.so)
==4150==    by 0x160A5044: ???
==4150==    by 0x160A67D6: ???
==4150==    by 0x160A6783: ???
==4150==    by 0x145E76D3: TCling::ExecuteWithArgsAndReturn(TMethod*, void*, void const**, int, void*) const (in /afs/cern.ch/cms/sw/ReleaseCandidates/volB/slc6_amd64_gcc491/lcg/root/6.02.00-lnjiaj2/lib/libCling.so)

Conflicts:
	interpreter/cling/lib/Interpreter/IncrementalExecutor.cpp
This commit is contained in:
Philippe Canal 2015-03-13 16:03:50 -05:00 committed by sftnight
parent 397921f678
commit 5842d86a2f
2 changed files with 28 additions and 8 deletions

View File

@ -9,6 +9,7 @@
#include "IncrementalExecutor.h"
#include "IncrementalJIT.h"
#include "Threading.h"
#include "cling/Interpreter/Value.h"
#include "cling/Interpreter/Transaction.h"
@ -48,6 +49,9 @@ IncrementalExecutor::IncrementalExecutor(clang::DiagnosticsEngine& diags):
: m_Diags(diags)
#endif
{
// No need to protect this access of m_AtExitFuncs, since nobody
// can use this object yet.
m_AtExitFuncs.reserve(256);
m_JIT.reset(new IncrementalJIT(*this, std::move(CreateHostTargetMachine())));
@ -88,6 +92,8 @@ std::unique_ptr<TargetMachine>
}
void IncrementalExecutor::shuttingDown() {
// No need to protect this access, since hopefully there is no concurrent
// shutdown request.
for (size_t I = 0, N = m_AtExitFuncs.size(); I < N; ++I) {
const CXAAtExitElement& AEE = m_AtExitFuncs[N - I - 1];
(*AEE.m_Func)(AEE.m_Arg);
@ -96,6 +102,7 @@ void IncrementalExecutor::shuttingDown() {
void IncrementalExecutor::AddAtExitFunc(void (*func) (void*), void* arg) {
// Register a CXAAtExit function
cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, m_CurrentAtExitModule));
}
@ -265,14 +272,18 @@ void IncrementalExecutor::runAndRemoveStaticDestructors(Transaction* T) {
assert(T && "Must be set");
// Collect all the dtors bound to this transaction.
AtExitFunctions boundToT;
for (AtExitFunctions::iterator I = m_AtExitFuncs.begin();
I != m_AtExitFuncs.end();)
if (I->m_FromM == T->getModule()) {
boundToT.push_back(*I);
I = m_AtExitFuncs.erase(I);
}
else
++I;
{
cling::internal::SpinLockGuard slg(m_AtExitFuncsSpinLock);
for (AtExitFunctions::iterator I = m_AtExitFuncs.begin();
I != m_AtExitFuncs.end();)
if (I->m_FromM == T->getModule()) {
boundToT.push_back(*I);
I = m_AtExitFuncs.erase(I);
}
else
++I;
} // end of spin lock lifetime block.
// 'Unload' the cxa_atexit entities.
for (AtExitFunctions::reverse_iterator I = boundToT.rbegin(),

View File

@ -23,6 +23,7 @@
#include <set>
#include <map>
#include <memory>
#include <atomic>
namespace clang {
class DiagnosticsEngine;
@ -89,6 +90,14 @@ namespace cling {
const llvm::Module* m_FromM;
};
///\brief Atomic used as a spin lock to protect the access to m_AtExitFuncs
///
/// AddAtExitFunc is used at the end of the 'interpreted' user code
/// and before the calling framework has any change of taking back/again
/// its lock protecting the access to cling, so we need to explicit protect
/// again multiple conccurent access.
std::atomic_flag m_AtExitFuncsSpinLock = ATOMIC_FLAG_INIT;
typedef llvm::SmallVector<CXAAtExitElement, 128> AtExitFunctions;
///\brief Static object, which are bound to unloading of certain declaration
/// to be destructed.