mirror of
https://github.com/XTXMarkets/ternfs.git
synced 2026-01-05 10:30:53 -06:00
See <https://mazzo.li/posts/stopping-linux-threads.html> for tradeoffs regarding how to terminate threads gracefully. The goal of this work was for valgrind to work correctly, which in turn was to investigate #141. It looks like I have succeeded: ==2715080== Warning: unimplemented fcntl command: 1036 ==2715080== 20,052 bytes in 5,013 blocks are definitely lost in loss record 133 of 135 ==2715080== at 0x483F013: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==2715080== by 0x3B708E: allocate (new_allocator.h:121) ==2715080== by 0x3B708E: allocate (allocator.h:173) ==2715080== by 0x3B708E: allocate (alloc_traits.h:460) ==2715080== by 0x3B708E: _M_allocate (stl_vector.h:346) ==2715080== by 0x3B708E: std::vector<Crc, std::allocator<Crc> >::_M_default_append(unsigned long) (vector.tcc:635) ==2715080== by 0x42BF1C: resize (stl_vector.h:940) ==2715080== by 0x42BF1C: ShardDBImpl::_fileSpans(rocksdb::ReadOptions&, FileSpansReq const&, FileSpansResp&) (shard/ShardDB.cpp:921) ==2715080== by 0x420867: ShardDBImpl::read(ShardReqContainer const&, ShardRespContainer&) (shard/ShardDB.cpp:1034) ==2715080== by 0x3CB3EE: ShardServer::_handleRequest(int, sockaddr_in*, char*, unsigned long) (shard/Shard.cpp:347) ==2715080== by 0x3C8A39: ShardServer::step() (shard/Shard.cpp:405) ==2715080== by 0x40B1E8: run (core/Loop.cpp:67) ==2715080== by 0x40B1E8: startLoop(void*) (core/Loop.cpp:37) ==2715080== by 0x4BEA258: start_thread (in /usr/lib/libpthread-2.33.so) ==2715080== by 0x4D005E2: clone (in /usr/lib/libc-2.33.so) ==2715080== ==2715080== ==2715080== Exit program on first error (--exit-on-first-error=yes)
55 lines
2.1 KiB
C++
55 lines
2.1 KiB
C++
#pragma once
|
|
|
|
#include "Exception.hpp"
|
|
#include "Time.hpp"
|
|
#include "Env.hpp"
|
|
#include "Loop.hpp"
|
|
#include "wyhash.h"
|
|
|
|
struct PeriodicLoopConfig {
|
|
Duration failureInterval; // waiting between failures
|
|
double failureIntervalJitter = 1.0;
|
|
Duration successInterval; // waiting between successes
|
|
double successIntervalJitter = 1.0;
|
|
|
|
PeriodicLoopConfig(Duration failureInterval_, Duration successInterval_) : failureInterval(failureInterval_), successInterval(successInterval_) {}
|
|
PeriodicLoopConfig(Duration failureInterval_, double failureIntervalJitter_, Duration successInterval_, double successIntervalJitter_) :
|
|
failureInterval(failureInterval_), failureIntervalJitter(failureIntervalJitter_), successInterval(successInterval_), successIntervalJitter(successIntervalJitter_)
|
|
{}
|
|
};
|
|
|
|
struct PeriodicLoop : Loop {
|
|
private:
|
|
PeriodicLoopConfig _config;
|
|
uint64_t _rand;
|
|
bool _lastSucceded;
|
|
|
|
public:
|
|
PeriodicLoop(Logger& logger, std::shared_ptr<XmonAgent>& xmon, const std::string& name, const PeriodicLoopConfig& config) :
|
|
Loop(logger, xmon, name),
|
|
_config(config),
|
|
_rand(eggsNow().ns),
|
|
_lastSucceded(false)
|
|
{}
|
|
|
|
// true = success, false = failure
|
|
virtual bool periodicStep() = 0;
|
|
|
|
// We sleep first to immediately introduce a jitter.
|
|
virtual void step() override {
|
|
auto t = eggsNow();
|
|
Duration pause;
|
|
if (_lastSucceded) {
|
|
pause = _config.successInterval + Duration((double)_config.successInterval.ns * (_config.successIntervalJitter * wyhash64_double(&_rand)));
|
|
LOG_DEBUG(_env, "periodic step succeeded, next step at %s", t + pause);
|
|
} else {
|
|
pause = _config.failureInterval + Duration((double)_config.failureInterval.ns * (_config.failureIntervalJitter * wyhash64_double(&_rand)));
|
|
LOG_DEBUG(_env, "periodic step failed, next step at %s", t + pause);
|
|
}
|
|
if (sleep(pause) < 0) {
|
|
if (errno == EINTR) { return; }
|
|
throw SYSCALL_EXCEPTION("sleep");
|
|
}
|
|
_lastSucceded = periodicStep();
|
|
}
|
|
}; |