[PATCH] D115232: [clangd] Indexing of standard library
Sam McCall via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Wed Dec 21 10:09:22 PST 2022
sammccall added inline comments.
================
Comment at: clang-tools-extra/clangd/ClangdServer.cpp:1008-1010
+ // TUScheduler is the only thing that starts background indexing work.
+ if (IndexTasks && !IndexTasks->wait(timeoutSeconds(TimeoutSeconds)))
+ return false;
----------------
bnbarham wrote:
> @sammccall shouldn't we also be waiting for this to finish when `ClangdServer` is destroyed? IIUC right now the both `FileIndex` itself (stored in `ClangdServer`) and the actual `UpdateIndexCallbacks` (stored in `TUScheduler`) can be freed while `indexStdlib` is running asynchronously, resulting in a use-after-free on eg. `FIndex->updatePreamble(std::move(IF))`. I was confused as to why this wasn't happening in the tests, but these lines would explain it 😅
>
> Adding a `IndexTasks->wait()` to `~ClangdServer` fixes the crash I'm seeing in the sourcekit-lsp tests (see https://github.com/apple/llvm-project/pull/5837), though ideally we (sourcekit-lsp) wouldn't be running any indexing at all. As far as I can tell there's no way to turn off dynamic indexing now though, except for `StandardLibrary` indexing through the config file (but not from clangd args)?
Thanks for flagging this!
We *almost* have the sequencing we need in ~ClangdServer:
- when we fall off the end of ~ClangdServer it destroys all its members
- `ClangdServer::IndexTasks` is declared after `FIndex`, so is destroyed first
- ~AsyncTaskRunner calls `wait()`
But the task we schedule on `IndexTasks` captures a ref to `UpdateIndexCallbacks`, which is owned by the `TUScheduler`, which we explicitly destroy at the beginning of `~ClangdServer`.
However I think your patch is *also* not quite correct: we can wait for the tasks to be empty, but then the TUScheduler could fill it up again before we destroy TUScheduler.
Options include adding an explicit stop() to TUScheduler, changing TUScheduler to not (exclusively) own UpdateIndexCallbacks, or have the task not capture the callbacks by reference.
I'll try the latter first, which seems least invasive.
---
> ideally we (sourcekit-lsp) wouldn't be running any indexing at all. As far as I can tell there's no way to turn off dynamic indexing now though, except for StandardLibrary indexing through the config file (but not from clangd args)?
Clangd won't provide any top-level/namespace-level completions at all without dynamic index (index of preambles), and various other features won't work (docs on hover, include-fixer, type/call-hierarchy). We dropped support for disabling this at some point, as it didn't really seem usable and made features more complex if we tried to accommodate it. At a technical level it would be possible to disable I think, but I'd be really surprised if completion worked well, or if a language server without completion was useful.
> `StandardLibrary` indexing through the config file (but not from clangd args)
We've tried to move away from flags for options that are interesting to users, as config files are more flexible, more forgiving on errors, and allow different settings per-project in a consistent way. (We don't own the editors, so cross-editor consistency is important to being able to support users at all...)
I can see how requiring config to be materialized on disk could be inconvenient for IDEs though. I think we could add a general-purpose `--config-inline=<YAML/JSON goes here>` flag, and/or the ability to set config over LSP (this can be dynamic, accordingly bigger design space that might be hard to get right).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D115232/new/
https://reviews.llvm.org/D115232
More information about the cfe-commits
mailing list