indexer: add extra fsm state "finishing" to fix some races

As reported by helgrind
This commit is contained in:
Dirk-Jan C. Binnema 2022-05-13 23:00:20 +03:00
parent 201acfbbd3
commit 4edbe01aa0
1 changed files with 16 additions and 13 deletions

View File

@ -42,14 +42,16 @@ using namespace Mu;
struct IndexState { struct IndexState {
enum State { Idle, enum State { Idle,
Scanning, Scanning,
Finishing,
Cleaning }; Cleaning };
static const char* name(State s) static const char* name(State s) {
{
switch (s) { switch (s) {
case Idle: case Idle:
return "idle"; return "idle";
case Scanning: case Scanning:
return "scanning"; return "scanning";
case Finishing:
return "finishing";
case Cleaning: case Cleaning:
return "cleaning"; return "cleaning";
default: default:
@ -58,16 +60,16 @@ struct IndexState {
} }
bool operator==(State rhs) const { bool operator==(State rhs) const {
return state_ == rhs; return state_.load() == rhs;
} }
bool operator!=(State rhs) const { bool operator!=(State rhs) const {
return state_ != rhs; return state_.load() != rhs;
} }
void change_to(State new_state) { void change_to(State new_state) {
g_debug("changing indexer state %s->%s", name((State)state_), g_debug("changing indexer state %s->%s", name((State)state_),
name((State)new_state)); name((State)new_state));
state_ = new_state; state_.store(new_state);
} }
private: private:
@ -80,15 +82,13 @@ struct Indexer::Private {
[this](auto&& path, auto&& statbuf, auto&& info) { [this](auto&& path, auto&& statbuf, auto&& info) {
return handler(path, statbuf, info); return handler(path, statbuf, info);
}}, }},
max_message_size_{store_.properties().max_message_size} max_message_size_{store_.properties().max_message_size} {
{
g_message("created indexer for %s -> %s (batch-size: %zu)", g_message("created indexer for %s -> %s (batch-size: %zu)",
store.properties().root_maildir.c_str(), store.properties().root_maildir.c_str(),
store.properties().database_path.c_str(), store.properties().batch_size); store.properties().database_path.c_str(), store.properties().batch_size);
} }
~Private() ~Private() {
{
stop(); stop();
} }
@ -305,7 +305,8 @@ Indexer::Private::scan_worker()
g_debug("starting scanner"); g_debug("starting scanner");
if (!scanner_.start()) { // blocks. if (!scanner_.start()) { // blocks.
g_warning("failed to start scanner"); g_warning("failed to start scanner");
goto leave; state_.change_to(IndexState::Idle);
return;
} }
g_debug("scanner finished with %zu file(s) in queue", todos_.size()); g_debug("scanner finished with %zu file(s) in queue", todos_.size());
} }
@ -324,8 +325,11 @@ Indexer::Private::scan_worker()
while (!todos_.empty()) while (!todos_.empty())
std::this_thread::sleep_for(100ms); std::this_thread::sleep_for(100ms);
} }
// and let the worker finish their work.
store_.commit(); state_.change_to(IndexState::Finishing);
for (auto&& w : workers_)
if (w.joinable())
w.join();
if (conf_.cleanup) { if (conf_.cleanup) {
g_debug("starting cleanup"); g_debug("starting cleanup");
@ -335,7 +339,6 @@ Indexer::Private::scan_worker()
g_debug("cleanup finished"); g_debug("cleanup finished");
} }
leave:
store_.index_complete(); store_.index_complete();
state_.change_to(IndexState::Idle); state_.change_to(IndexState::Idle);
} }