This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Support external throttler for preamble builds
ClosedPublic

Authored by sammccall on Jul 4 2022, 5:33 PM.

Details

Summary

Building preambles is the most resource-intensive thing clangd does, driving
peak RAM and sustained CPU usage.

In a hosted environment where multiple clangd instances are packed into the same
container, it's useful to be able to limit the *aggregate* resource peaks.

Diff Detail

Event Timeline

sammccall created this revision.Jul 4 2022, 5:33 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 4 2022, 5:33 PM
sammccall requested review of this revision.Jul 4 2022, 5:33 PM

I wanted to send a first version out for feedback even if incomplete.
(I want to do more extensive tests, and likely we should think about having an in-tree throttler on by default)

To motivate the design:

  • when attempting to acquire a slot, we want to wait on (acquired || shutting down).
  • This means sharing a condition variable for both events, as we can't wait on multiple conditions.
  • this leads to the callback-based model for PreambleThrottler, the callback lets us encapsulate the use of a shared CV in this way
  • the acquire callback naturally accesses the PreambleThread, but it might have gone away concurrently. This is awkward to solve in a callback API.
  • The chosen solution is to heap-allocate a small object that can own the state the callback needs to access
sammccall planned changes to this revision.Jul 5 2022, 5:40 AM

Summarizing an offline discussion:

  • ThrottlerState isolates complexity inside TUScheduler by absolving Throttler of the need to worry about callback lifetimes
  • but it does so at the cost of extra aggregate complexity (third object with different lifetime & own threading model)
  • the main alternative seems to be to allow deregistration of callbacks on throttler (addListener/removeListener)
    • planning to give that a try.

we've already discussed most of these so no action needed, but here are some of them before they become completely irrelevant :P

clang-tools-extra/clangd/TUScheduler.cpp
472–482

any reason for capturing locals here now ?

492

in the scenario of a shutdown (or destruction of a preamble thread, because file is closed), i think we also want to call cancellation of the acquire release here. as things stand unless we're destroying the throttler itself i think these requests might stick around.

499

we can move the wait into the if block above, i think.

499

so this implies preamblerequest we issued an acquire for, and the preamble request we'll be building below might be different. this is not a concern initially but i think it would be nice to not get cornered when we want to notify the throttler about such changes.

i guess PreambleThread::update would be the natural place to communicate such changes, if we're overwriting a preamblerequest and there's a pending acquire we can either cancel and make preamblethread re-issue acquire, or we can have a new API on throttler to update the request signals. i think, both of these require having throttlestate as a member. maybe we should do that directly to remind ourselves of this in the future?

1554

let's use "includes" here, similar to above.

clang-tools-extra/clangd/TUScheduler.h
114

can we make the first parameter a struct instead? i feel like we might end up adding more parameters describing the reason for the request here.

sammccall updated this revision to Diff 442308.Jul 5 2022, 7:54 AM

Simplify, leaning more on the throttler's lifetime and expecting it to manage
state.

sammccall updated this revision to Diff 442309.Jul 5 2022, 7:56 AM

remove dead code

sammccall marked 2 inline comments as done.Jul 5 2022, 8:42 AM
sammccall added inline comments.
clang-tools-extra/clangd/TUScheduler.cpp
472–482

Just for consistency with the second wait below - I usually don't think it's interesting to list captures when no lifetimes are involved (because the lambda is invoked synchronously)

492

(this is obsolete, but...)

I don't think this leak is possible, after we get Cancel (from Throttler->acquire) then we wait until either:

  • request is satisfied (TState->ready() on line 500) in which case no cancel is needed, or
  • we call Cancel immediately on line 501.
499

we can move the wait into the if block

that works, but it doesn't really seem clearer to me

wait (..., cond) is just while (!cond) { ... }, so the outer if is redundant.
On the other hand the if is important to the code it currently guards (for reasons explained in the comment), so it seems confusing to split its purpose in this way.

The only way it makes sense to me is as a microoptimization, but it doesn't seem like a useful one.

499

the preamble request we'll be building below might be different

The request in general is (filename, signals). Filename clearly can't change. Signals can, but...

i guess PreambleThread::update would be the natural place to communicate such changes

I don't think so, I think signals naturally come from elsewhere in the system as (filename, signal) pairs and are best thought of as "sticky", where events affect both current and future throttling requests.

As such I think we might have an API like Throttler->updateSignals(Filename, ...) and let the throttler join on filename, rather than require this joining to be done artificially somewhere else in clangd.
One nice thing about this is if there's no throttler, we don't pay for keeping track of the signals.

sammccall updated this revision to Diff 442319.Jul 5 2022, 8:42 AM
sammccall marked an inline comment as done.

address review comments

kadircet accepted this revision.Jul 6 2022, 2:38 AM

thanks, lgtm!

clang-tools-extra/clangd/ClangdServer.h
108

why the qualification ?

clang-tools-extra/clangd/TUScheduler.cpp
414

use PreambleThrottler::RequestID instead of unsigned?

clang-tools-extra/clangd/TUScheduler.h
90

triple slashes here and inside the class

106

there's no cancel anymore.

clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
1499

sequencing is hard here but it'd be nice to ensure release is actually seen.

This revision is now accepted and ready to land.Jul 6 2022, 2:38 AM
sammccall marked 5 inline comments as done.Jul 6 2022, 5:45 AM
sammccall added inline comments.
clang-tools-extra/clangd/ClangdServer.h
108

same name is used for the type and the member name, an error in at least some compilers (I forget what the standard says).
I can't think of another good name

clang-tools-extra/clangd/TUScheduler.h
114

My hypothesis is that *all* other parameters will be provided separately on unrelated codepaths (Throttler->setFoo(Filename, Foo)) and the name here is a join key rather than one parameter among many.

I might be wrong about this but would rather hold off on generalizing until we're sure.

This revision was landed with ongoing or failed builds.Jul 6 2022, 5:58 AM
This revision was automatically updated to reflect the committed changes.
sammccall marked an inline comment as done.

This caused llvm builds to fail for me (using clang-14, debug, debian unstable, lld as linker):

FAILED: tools/clang/tools/extra/clangd/unittests/ClangdTests 
: && /usr/bin/clang++-14 -gz=zlib -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -fdiagnostics-color -fno-common -Woverloaded-virtual -Wno-nested-anon-types -g -Wl,-rpath,/home/andres/build/llvm-project/master/debug-clang/install/lib -Wl,--gdb-index -fuse-ld=lld -Wl,--gdb-index -Wl,--color-diagnostics tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/AddUsing.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/AnnotateHighlightings.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/DumpAST.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/DefineInline.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/DefineOutline.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/ExpandAutoType.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/ExpandMacro.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/ExtractFunction.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/ExtractVariable.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/MemberwiseConstructor.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/ObjCLocalizeStringLiteral.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/ObjCMemberwiseInitializer.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/PopulateSwitch.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/RawStringLiteral.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/RemoveUsingNamespace.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/SpecialMembers.cpp.o tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/SwapIfBranches.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/Annotations.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ASTTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ASTSignalsTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/BackgroundIndexTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/CallHierarchyTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/CanonicalIncludesTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ClangdTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ClangdLSPServerTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/CodeCompleteTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/CodeCompletionStringsTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/CollectMacrosTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/CompileCommandsTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/CompilerTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ConfigCompileTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ConfigProviderTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ConfigYAMLTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/DecisionForestTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/DexTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/DiagnosticsTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/DraftStoreTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/DumpASTTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ExpectedTypeTest.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/FeatureModulesTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/FileDistanceTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/FileIndexTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/FindSymbolsTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/FindTargetTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/FormatTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/FSTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/FuzzyMatchTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/GlobalCompilationDatabaseTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/HeadersTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/HeaderSourceSwitchTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/HoverTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/IncludeCleanerTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/IndexActionTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/IndexTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/InlayHintTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/InsertionPointTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/JSONTransportTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/LoggerTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/LSPBinderTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/LSPClient.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ModulesTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ParsedASTTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/PathMappingTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/PreambleTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/PrintASTTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ProjectAwareIndexTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/QualityTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/RenameTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/RIFFTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/SelectionTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/SemanticHighlightingTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/SemanticSelectionTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/SerializationTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/SourceCodeTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/StdLibTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/SymbolCollectorTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/SymbolInfoTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/SyncAPI.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TUSchedulerTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TestFS.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TestIndex.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TestTU.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TestWorkspace.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ThreadCrashReporterTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TidyProviderTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TypeHierarchyTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/URITests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/XRefsTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/DecisionForestRuntimeTest.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/support/CancellationTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/support/ContextTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/support/FunctionTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/support/MarkupTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/support/MemoryTreeTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/support/PathTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/support/ThreadingTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/support/TestTracer.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/support/TraceTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/AddUsingTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/AnnotateHighlightingsTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/DefineInlineTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/DefineOutlineTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/DumpASTTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/DumpRecordLayoutTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/DumpSymbolTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/ExpandAutoTypeTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/ExpandMacroTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/ExtractFunctionTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/ExtractVariableTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/MemberwiseConstructorTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/ObjCLocalizeStringLiteralTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/ObjCMemberwiseInitializerTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/PopulateSwitchTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/RawStringLiteralTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/RemoveUsingNamespaceTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/ShowSelectionTreeTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/SwapIfBranchesTests.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/TweakTesting.cpp.o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/tweaks/TweakTests.cpp.o -o tools/clang/tools/extra/clangd/unittests/ClangdTests  -Wl,-rpath,/home/andres/build/llvm-project/master/debug-clang/vpath/lib  -lpthread  lib/libllvm_gtest_main.so.15git  -lpthread  lib/libclangDaemon.so.15git  lib/libclangdSupport.so.15git  lib/libLLVMTestingSupport.so.15git  lib/libLLVMX86Info.so.15git  lib/libclangToolingSyntax.so.15git  lib/libclangTidy.so.15git  lib/libclangTooling.so.15git  lib/libclangToolingRefactoring.so.15git  lib/libclangIndex.so.15git  lib/libclangFormat.so.15git  lib/libclangToolingInclusions.so.15git  lib/libclangFrontend.so.15git  lib/libclangSerialization.so.15git  lib/libclangSema.so.15git  lib/libclangASTMatchers.so.15git  lib/libclangAST.so.15git  lib/libLLVMFrontendOpenMP.so.15git  lib/libclangToolingCore.so.15git  lib/libclangLex.so.15git  lib/libclangBasic.so.15git  lib/libllvm_gtest.so.15git  lib/libLLVMSupport.so.15git  -Wl,-rpath-link,/home/andres/build/llvm-project/master/debug-clang/vpath/lib && :
ld.lld: error: undefined symbol: vtable for clang::clangd::PreambleThrottler
>>> referenced by TUScheduler.h:97 (/home/andres/src/llvm-project/clang-tools-extra/clangd/TUScheduler.h:97)
>>>               tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TUSchedulerTests.cpp.o:(clang::clangd::PreambleThrottler::PreambleThrottler())
>>> the vtable symbol may be undefined because the class is missing its key function (see https://lld.llvm.org/missingkeyfunction)
clang: error: linker command failed with exit code 1 (use -v to see invocation)

This caused llvm builds to fail for me (using clang-14, debug, debian unstable, lld as linker):

Thanks, I have a very similar setup but the build passed locally, I'll never understand linkers...

I think I've fixed this in e7fa272bc6a6a504c2899bb7cf66029678d97890

Sorry about that, I believe this is fixed in eb64dbd6e0e617298579d32372fb92e595816d45.
(The flake symptoms I was able to see locally are different, but I would guess the same cause)

sammccall added inline comments.Jul 7 2022, 10:21 AM
clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
1499

So this turned out to be the cause of the test flakiness: the mechanism we discussed offline (context destruction) doesn't work.

The problem is that the context lives in the request, and we haven't moved the request from NextReq into CurrentReq yet (we're still throttling).
NextReq is destroyed when stop() is called. So S.remove(A) actually triggers AfterFinishA already, and then the following assertions race against the release() call.

I probably could have gotten this out of our tsan bot, but it's not producing any sanitizer logs (I suspect D122251).

In any case, this particular race is definitely only in the test, so disabling it until we have a real fix next week.

kadircet added inline comments.Jul 8 2022, 12:25 AM
clang-tools-extra/clangd/TUScheduler.cpp
499

regarding the flakiness, what about resetting the Throttle here to trigger the release? it's right after the build and would make sure release happens before the context is destroyed (+ we're not holding any locks)

sammccall added inline comments.Jul 8 2022, 3:05 AM
clang-tools-extra/clangd/TUScheduler.cpp
499

The critical case never gets here: done() is called while waiting for the throttler, and we never get to build anything.

(And by the time that wait is interrupted, the context is already concurrently being destroyed.)