mirror of
https://github.com/corda/corda.git
synced 2025-03-17 17:45:17 +00:00
fix race condition in compile function
1. Thread A calls function F, which needs to be compiled. So it compiles it. 2. Thread B calls function F, sees that it's already been compiled and so runs it. 3. Thread B calls function G from function F, and G needs to be compiled, but it needs to acquire the class lock first, which A owns. 4. Thread A causes a GC, walks thread B's stack, but function F has not yet been added to the method tree, so it thinks the stack has no frames. 5. Thread A finally adds function F to the method tree. 6. Thread A causes another GC and walks thread B's stack again, and this time it finds function F in the method tree. 7. AAAARRRRRGGGHHH!!!!!!
This commit is contained in:
parent
befdfa4e9e
commit
0b79ab4fed
@ -4255,7 +4255,7 @@ visitStack(MyThread* t, Heap::Visitor* v)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -5074,42 +5074,40 @@ compile(MyThread* t, object method)
|
||||
{
|
||||
MyProcessor* p = processor(t);
|
||||
|
||||
if (methodCompiled(t, method) == p->defaultThunk) {
|
||||
PROTECT(t, method);
|
||||
PROTECT(t, method);
|
||||
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
ACQUIRE(t, t->m->classLock);
|
||||
|
||||
if (methodCompiled(t, method) == p->defaultThunk) {
|
||||
initClass(t, methodClass(t, method));
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
|
||||
if (methodCompiled(t, method) == p->defaultThunk) {
|
||||
initClass(t, methodClass(t, method));
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
object compiled;
|
||||
if (methodFlags(t, method) & ACC_NATIVE) {
|
||||
compiled = p->nativeThunk;
|
||||
} else {
|
||||
Context context(t, method);
|
||||
compiled = compile(t, &context);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
}
|
||||
|
||||
if (methodCompiled(t, method) == p->defaultThunk) {
|
||||
object compiled;
|
||||
if (methodFlags(t, method) & ACC_NATIVE) {
|
||||
compiled = p->nativeThunk;
|
||||
} else {
|
||||
Context context(t, method);
|
||||
compiled = compile(t, &context);
|
||||
if (UNLIKELY(t->exception)) return;
|
||||
set(t, method, MethodCompiled, compiled);
|
||||
|
||||
if (methodVirtual(t, method)) {
|
||||
classVtable(t, methodClass(t, method), methodOffset(t, method))
|
||||
= &singletonValue(t, compiled, 0);
|
||||
}
|
||||
|
||||
if ((methodFlags(t, method) & ACC_NATIVE) == 0) {
|
||||
if (DebugMethodTree) {
|
||||
fprintf(stderr, "insert method at %p\n",
|
||||
&singletonValue(t, methodCompiled(t, method), 0));
|
||||
}
|
||||
|
||||
set(t, method, MethodCompiled, compiled);
|
||||
|
||||
if (methodVirtual(t, method)) {
|
||||
classVtable(t, methodClass(t, method), methodOffset(t, method))
|
||||
= &singletonValue(t, compiled, 0);
|
||||
}
|
||||
|
||||
if ((methodFlags(t, method) & ACC_NATIVE) == 0) {
|
||||
if (DebugMethodTree) {
|
||||
fprintf(stderr, "insert method at %p\n",
|
||||
&singletonValue(t, methodCompiled(t, method), 0));
|
||||
}
|
||||
|
||||
methodTree(t) = treeInsert
|
||||
(t, methodTree(t), method, methodTreeSentinal(t),
|
||||
compareMethodBounds);
|
||||
}
|
||||
methodTree(t) = treeInsert
|
||||
(t, methodTree(t), method, methodTreeSentinal(t),
|
||||
compareMethodBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user