Skip to content

Commit 65951e0

Browse files
ryanofskyfurszy
authored andcommitted
index: race fix, lock cs_main while 'm_synced' is subject to change
This ensures that the index does not miss any 'new block' signals occurring in-between reading the 'next block' and setting 'm_synced'. Because, if this were to happen, the ignored blocks would never be indexed, thus stalling the index forever.
1 parent 3f6a6da commit 65951e0

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

src/index/base.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,24 @@ void BaseIndex::Sync()
160160
}
161161

162162
const CBlockIndex* pindex_next = WITH_LOCK(cs_main, return NextSyncBlock(pindex, m_chainstate->m_chain));
163+
// If pindex_next is null, it means pindex is the chain tip, so
164+
// commit data indexed so far.
163165
if (!pindex_next) {
164166
SetBestBlockIndex(pindex);
165167
// No need to handle errors in Commit. See rationale above.
166168
Commit();
167-
m_synced = true;
168-
break;
169+
170+
// If pindex is still the chain tip after committing, exit the
171+
// sync loop. It is important for cs_main to be locked while
172+
// setting m_synced = true, otherwise a new block could be
173+
// attached while m_synced is still false, and it would not be
174+
// indexed.
175+
LOCK(::cs_main);
176+
pindex_next = NextSyncBlock(pindex, m_chainstate->m_chain);
177+
if (!pindex_next) {
178+
m_synced = true;
179+
break;
180+
}
169181
}
170182
if (pindex_next->pprev != pindex && !Rewind(pindex, pindex_next->pprev)) {
171183
FatalErrorf("%s: Failed to rewind index %s to a previous chain tip", __func__, GetName());

0 commit comments

Comments
 (0)