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:
parent
397921f678
commit
5842d86a2f
@ -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(),
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user