[sourcekit] Synchronize cursor-info requests on generated interfaces

Cursor info requires access to the underlying AST, which is not
thread-safe. This manifest as crashes when performing concurrent
cursor-info requests on the same generated interface. We already
prevented concurrent cursor-infos on regular Swift files by using the
ASTManager, but generated interfaces use the InterfaceGenContext which
may use either an ASTUnit or its own internal CompilerInstance.

rdar://problem/27311624
This commit is contained in:
Ben Langmuir
2016-07-13 16:22:04 -07:00
parent 8e0ff518d1
commit 18be066651
6 changed files with 76 additions and 18 deletions

View File

@@ -1024,24 +1024,26 @@ void SwiftLangSupport::getCursorInfo(
SwiftArgs, OpArgs);
}
SwiftInterfaceGenContext::ResolvedEntity Entity;
Entity = IFaceGenRef->resolveEntityForOffset(Offset);
if (Entity.isResolved()) {
CompilerInvocation Invok;
IFaceGenRef->applyTo(Invok);
if (Entity.Mod) {
passCursorInfoForModule(Entity.Mod, IFaceGenContexts, Invok, Receiver);
IFaceGenRef->accessASTAsync([this, IFaceGenRef, Offset, Receiver] {
SwiftInterfaceGenContext::ResolvedEntity Entity;
Entity = IFaceGenRef->resolveEntityForOffset(Offset);
if (Entity.isResolved()) {
CompilerInvocation Invok;
IFaceGenRef->applyTo(Invok);
if (Entity.Mod) {
passCursorInfoForModule(Entity.Mod, IFaceGenContexts, Invok,
Receiver);
} else {
// FIXME: Should pass the main module for the interface but currently
// it's not necessary.
passCursorInfoForDecl(
Entity.Dcl, /*MainModule*/ nullptr, Type(), Type(), Entity.IsRef,
/*OrigBufferID=*/None, *this, Invok, {}, Receiver);
}
} else {
// FIXME: Should pass the main module for the interface but currently
// it's not necessary.
passCursorInfoForDecl(Entity.Dcl, /*MainModule*/nullptr, Type(), Type(),
Entity.IsRef,
/*OrigBufferID=*/None, *this, Invok,
{}, Receiver);
Receiver({});
}
} else {
Receiver({});
}
});
return;
}