-#include <boost/format/format_fwd.hpp>
+#include <algorithm>
+#include <condition_variable>
+#include <future>
+#include <random>
#include <stdexcept>
#include <thread>
-#include <future>
+#include <tuple>
+#include <utility>
+#include <variant>
#include <boost/format.hpp>
+#include <boost/format/format_fwd.hpp>
#include <boost/uuid/string_generator.hpp>
#include <boost/algorithm/string/erase.hpp>
-#include <utility>
-#include <algorithm>
-#include <random>
+
#include "misc.hh"
#include "qtype.hh"
-#include <tuple>
-#include <variant>
#include "version.hh"
#include "ext/luawrapper/include/LuaContext.hpp"
#include "lock.hh"
std::chrono::system_clock::time_point checkStart = std::chrono::system_clock::now();
std::vector<std::future<void>> results;
std::vector<CheckDesc> toDelete;
- time_t interval{g_luaHealthChecksInterval};
{
// make sure there's no insertion
auto statuses = d_statuses.read_lock();
for (auto& it: *statuses) {
auto& desc = it.first;
auto& state = it.second;
+ time_t interval{g_luaHealthChecksInterval};
time_t checkInterval{0};
auto lastAccess = std::chrono::system_clock::from_time_t(state->lastAccess);
// set thread name again, in case std::async surprised us by doing work in this thread
setThreadName("pdns/luaupcheck");
- // Only sleep for 1 second here, even if the health check interval is
- // larger, in case we get new entries to process in d_statuses in the
- // meantime.
- std::this_thread::sleep_for(std::chrono::seconds(1));
+ // Wait for at most one complete check interval, but allow an earlier
+ // wakeup in case more work is being put in d_statuses.
+ {
+ std::unique_lock<std::mutex> lock(d_mutex);
+ auto sleepTime = std::chrono::seconds(g_luaHealthChecksInterval) - (std::chrono::system_clock::now() - checkStart);
+ if (sleepTime > std::chrono::seconds::zero()) {
+ d_condvar.wait_until(lock, std::chrono::system_clock::now() + sleepTime);
+ }
+ }
}
}
std::unique_ptr<std::thread> d_checkerThread;
std::atomic_flag d_checkerThreadStarted;
+ std::mutex d_mutex; // used with the condition variable below
+ std::condition_variable d_condvar;
+
void setStatus(const CheckDesc& cd, bool status)
{
auto statuses = d_statuses.write_lock();
(*statuses)[cd] = std::make_unique<CheckState>(now);
}
}
- // Now that we have given it work to do, make sure the checker thread runs.
+ // Now that we have given it work to do, make sure the checker thread runs,
+ // and notify it if it had already been running.
if (!d_checkerThreadStarted.test_and_set()) {
d_checkerThread = std::make_unique<std::thread>([this] { return checkThread(); });
}
+ else {
+ d_condvar.notify_all();
+ }
// If explicitly asked to fail on incomplete checks, report this (as
// a negative value).
static const std::string foic{"failOnIncompleteCheck"};