Skip to content

Commit

Permalink
Added support for POSIX signals in the replay steemit#551
Browse files Browse the repository at this point in the history
  • Loading branch information
leinlawun authored and On1x committed Jul 3, 2018
1 parent a4a4109 commit d7f5e82
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 0 deletions.
109 changes: 109 additions & 0 deletions libraries/chain/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
#include <fc/io/fstream.hpp>
#include <fc/io/json.hpp>

#include <appbase/application.hpp>
#include <csignal>
#include <cerrno>
#include <cstring>

#define VIRTUAL_SCHEDULE_LAP_LENGTH ( fc::uint128_t(uint64_t(-1)) )
#define VIRTUAL_SCHEDULE_LAP_LENGTH2 ( fc::uint128_t::max_value() )

Expand Down Expand Up @@ -72,6 +77,7 @@ FC_REFLECT((golos::chain::snapshot_items), (accounts))

namespace golos { namespace chain {

using std::sig_atomic_t;
using boost::container::flat_set;

inline u256 to256(const fc::uint128_t &t) {
Expand All @@ -81,6 +87,98 @@ namespace golos { namespace chain {
return v;
}

class signal_guard {
struct sigaction old_hup_action, old_int_action, old_term_action;

static volatile sig_atomic_t is_interrupted;

bool is_restored = true;

static inline void throw_exception();

public:
inline signal_guard();

inline ~signal_guard();

void setup();

void restore();

static inline sig_atomic_t get_is_interrupted() noexcept;
};

volatile sig_atomic_t signal_guard::is_interrupted = false;

inline void signal_guard::throw_exception() {
FC_THROW_EXCEPTION(database_signal_exception,
"Error setup signal handler: ${e}.",
("e", strerror(errno)));
}

inline signal_guard::signal_guard() {
setup();
}

inline signal_guard::~signal_guard() {
try {
restore();
}
FC_CAPTURE_AND_LOG(())
}

void signal_guard::setup() {
if (is_restored) {
struct sigaction new_action;

new_action.sa_handler = [](int signum) {
is_interrupted = true;
};
new_action.sa_flags = SA_RESTART;

if (sigemptyset(&new_action.sa_mask) == -1) {
throw_exception();
}

if (sigaction(SIGHUP, &new_action, &old_hup_action) == -1) {
throw_exception();
}

if (sigaction(SIGINT, &new_action, &old_int_action) == -1) {
throw_exception();
}

if (sigaction(SIGTERM, &new_action, &old_term_action) == -1) {
throw_exception();
}

is_restored = false;
}
}

void signal_guard::restore() {
if (!is_restored) {
if (sigaction(SIGHUP, &old_hup_action, nullptr) == -1) {
throw_exception();
}

if (sigaction(SIGINT, &old_int_action, nullptr) == -1) {
throw_exception();
}

if (sigaction(SIGTERM, &old_term_action, nullptr) == -1) {
throw_exception();
}

is_interrupted = false;
is_restored = true;
}
}

inline sig_atomic_t signal_guard::get_is_interrupted() noexcept {
return is_interrupted;
}

class database_impl {
public:
database_impl(database &self);
Expand Down Expand Up @@ -167,6 +265,7 @@ namespace golos { namespace chain {

void database::reindex(const fc::path &data_dir, const fc::path &shared_mem_dir, uint32_t from_block_num, uint64_t shared_file_size) {
try {
signal_guard sg;
_fork_db.reset(); // override effect of _fork_db.start_block() call in open()

auto start = fc::time_point::now();
Expand Down Expand Up @@ -194,6 +293,10 @@ namespace golos { namespace chain {

set_reserved_memory(1024*1024*1024); // protect from memory fragmentations ...
while (cur_block_num < last_block_num) {
if (signal_guard::get_is_interrupted()) {
return;
}

auto end = fc::time_point::now();
auto cur_block = *_block_log.read_block_by_num(cur_block_num);

Expand Down Expand Up @@ -221,6 +324,12 @@ namespace golos { namespace chain {
set_revision(head_block_num());
});

if (signal_guard::get_is_interrupted()) {
sg.restore();

appbase::app().quit();
}

if (_block_log.head()->block_num()) {
_fork_db.start_block(*_block_log.head());
}
Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/include/golos/chain/database_exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ namespace golos {

FC_DECLARE_DERIVED_EXCEPTION(database_revision_exception, golos::chain::chain_exception, 4120000, "database revision exception")

FC_DECLARE_DERIVED_EXCEPTION(database_signal_exception, golos::chain::chain_exception, 4130000, "database signal exception")

}
} // golos::chain

Expand Down

0 comments on commit d7f5e82

Please sign in to comment.