This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Fix race in background index rebuild, where index could stay stale.
Needs ReviewPublic

Authored by sammccall on Nov 2 2020, 4:50 AM.

Details

Reviewers
kadircet
Summary

The BackgroundQueue worker that finishes the last task is responsible for
calling OnIdle(). However calling OnIdle itself may be the "last task"
necessitating another call to OnIdle!

Consider:

Main      +T1 +T2            +T3
Worker1      [---T1---]       [---T3---]
Worker2           [---T2---][---Idle1---]

Idle1 starts running before T3 has started, let alone finished.
So it doesn't satisfy the goal that OnIdle runs after other work.

On the other hand, Worker1 won't run OnIdle after T3, as Idle1 is still running.
Therefore Worker2 needs to run OnIdle again (Idle2) once Idle1 completes.
This patch does that.

An example test flake due to this oversight:
http://lab.llvm.org:8011/#/builders/100/builds/721/steps/7/logs/FAIL__Clangd_Unit_Tests__BackgroundIndexTest_Confi

Diff Detail

Event Timeline

sammccall created this revision.Nov 2 2020, 4:50 AM
Herald added a project: Restricted Project. · View Herald TranscriptNov 2 2020, 4:50 AM
sammccall requested review of this revision.Nov 2 2020, 4:50 AM
kadircet added inline comments.Nov 3 2020, 6:05 AM
clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp
848

s/caute/cause

850

as discussed offline there are no guarantees on these newly pushed tasks finishing before the OnIdle.

kadircet added inline comments.Feb 9 2021, 3:36 AM
clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp
850

i suppose we can do something like:

  • Count number of times OnIdle has been executed.
  • Enqueue 2 more tasks with first OnIdle.
  • Assert that OnIdle has run twice ? (once on initial idleness, and once after completing 2 newly introduced tasks)