void ConfigApi::configThreadRun() { mcrouterSetThreadName(pthread_self(), opts_, "mcrcfg"); if (opts_.constantly_reload_configs) { while (!finish_) { LOG(INFO) << "Reload config due to constantly_reload_configs"; callbacks_.notify(); { std::unique_lock<std::mutex> lk(finishMutex_); finishCV_.wait_for(lk, std::chrono::milliseconds(10), [this] { return finish_.load(); }); } } return; } while (!finish_) { bool hasUpdate = false; try { hasUpdate = checkFileUpdate(); } catch (const std::exception& e) { logFailure(memcache::failure::Category::kOther, "Check for config update failed: {}", e.what()); } catch (...) { logFailure(memcache::failure::Category::kOther, "Check for config update failed with unknown error"); } // There are a couple of races that can happen here // First, the IN_MODIFY event can be fired before the write is complete, // resulting in a malformed JSON error. Second, text editors may do // some of their own shuffling of the file (e.g. between .swp and the // real thing in Vim) after the write. This may can result in a file // access error router_configure_from_file below. That's just a theory, // but that error does happen. Race 1 can be fixed by changing the // watch for IN_MODIFY to IN_CLOSE_WRITE, but Race 2 has no apparent // elegant solution. The following jankiness fixes both. { std::unique_lock<std::mutex> lk(finishMutex_); finishCV_.wait_for( lk, std::chrono::milliseconds(opts_.reconfiguration_delay_ms), [this] { return finish_.load(); }); } if (hasUpdate) { callbacks_.notify(); } // Otherwise there was nothing to read, so check that we aren't shutting // down, and wait on the FD again. } }
void ConfigApi::configThreadRun() { mcrouter_set_thread_name(pthread_self(), opts_, "mcrcfg"); if (opts_.constantly_reload_configs) { while (!finish_) { LOG(INFO) << "Reload config due to constantly_reload_configs"; callbacks_.notify(); usleep(10000); } return; } while (!finish_) { bool hasUpdate; try { hasUpdate = checkFileUpdate(); } catch (const std::exception& e) { LOG(ERROR) << "Check for config update failed: " << e.what(); return; } catch (...) { LOG(ERROR) << "Check for config update failed with unknown error"; return; } // There are a couple of races that can happen here // First, the IN_MODIFY event can be fired before the write is complete, // resulting in a malformed JSON error. Second, text editors may do // some of their own shuffling of the file (e.g. between .swp and the // real thing in Vim) after the write. This may can result in a file // access error router_configure_from_file below. That's just a theory, // but that error does happen. Race 1 can be fixed by changing the // watch for IN_MODIFY to IN_CLOSE_WRITE, but Race 2 has no apparent // elegant solution. The following jankiness fixes both. sleep(1); if (hasUpdate) { callbacks_.notify(); } // Otherwise there was nothing to read, so check that we aren't shutting // down, and wait on the FD again. } }