As vfs::FileSystem is not threadsafe, we've introduced a data race when
PreambleThread started to run in async mode. As both ASTWorker and
PreambleWorker can concurrently work on the same FS.
This patch fixes that data race by propagating FSProvider into TUScheduler and
ASTWorker and making use of a new FS when issuing update to the PreambleThread.
This doesn't break our contract on FSProvider::getFileSystem, as it says the
active context will be client's context at the time of request and
ASTWorker::update is run with the context we've captured on
ClangdServer::AddDocument.
As for the operations, this implies preamble and ast threads can see different
versions of the filesystems. For example in presence of a snapshotted filesystem
- client makes an AddDocument request with FS at snapshot v1
- client then updates the FS to v2
- ASTWorker starts handling the update, caches the FS v1 in FileInputs, which is used for serving reads.
- Schedules a preamble update, this fetches a new FS from provider, which might yield v2. This says might as clients can handle this case by storing snapshot version in context.
- Preamble build finishes and clangd publishes diagnostics for FS v2.
- Client issues a read (e.g. go-to-def), clangd uses FS v1 for serving the request.
This can be overcome by 2 filesystems into TUScheduler in
ClangdServer::AddDocument, but I don't think it is an issue in practice
currently. As our beloved snapshotted filesystem provider stores the snapshot
version in context, and should always return the same FS for requests coming
from the same context.
Yikes, ISTM we're getting the FS from Inputs here, and from this->FSProvider below. We should use one or the other (i.e. FSProvider only, following this patch) unless we're trying to do something really subtle...