Skip to content

Commit

Permalink
GH-1406 Re-create code cache on startup if it is corrupt
Browse files Browse the repository at this point in the history
  • Loading branch information
heifner committed Oct 16, 2023
1 parent 6cb1237 commit d6882dd
Showing 1 changed file with 30 additions and 13 deletions.
43 changes: 30 additions & 13 deletions libraries/chain/webassembly/runtimes/eos-vm-oc/code_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,34 +224,51 @@ const code_descriptor* const code_cache_sync::get_descriptor_for_code_sync(const

code_cache_base::code_cache_base(const boost::filesystem::path data_dir, const eosvmoc::config& eosvmoc_config, const chainbase::database& db) :
_db(db),
_cache_file_path(data_dir/"code_cache.bin")
{
_cache_file_path(data_dir/"code_cache.bin") {
static_assert(sizeof(allocator_t) <= header_offset, "header offset intersects with allocator");

bfs::create_directories(data_dir);

if(!bfs::exists(_cache_file_path)) {
EOS_ASSERT(eosvmoc_config.cache_size >= allocator_t::get_min_size(total_header_size), database_exception, "configured code cache size is too small");
bool created_file = false;
auto create_code_cache_file = [&] {
EOS_ASSERT(eosvmoc_config.cache_size >= allocator_t::get_min_size(total_header_size), database_exception,
"configured code cache size is too small");
std::ofstream ofs(_cache_file_path.generic_string(), std::ofstream::trunc);
EOS_ASSERT(ofs.good(), database_exception, "unable to create EOS VM Optimized Compiler code cache");
bfs::resize_file(_cache_file_path, eosvmoc_config.cache_size);
bip::file_mapping creation_mapping(_cache_file_path.generic_string().c_str(), bip::read_write);
bip::mapped_region creation_region(creation_mapping, bip::read_write);
new (creation_region.get_address()) allocator_t(eosvmoc_config.cache_size, total_header_size);
new ((char*)creation_region.get_address() + header_offset) code_cache_header;
created_file = true;
};

if (!bfs::exists(_cache_file_path)) {
create_code_cache_file();
}

code_cache_header cache_header;
{
char header_buff[total_header_size];
std::ifstream hs(_cache_file_path.generic_string(), std::ifstream::binary);
hs.read(header_buff, sizeof(header_buff));
EOS_ASSERT(!hs.fail(), bad_database_version_exception, "failed to read code cache header");
memcpy((char*)&cache_header, header_buff + header_offset, sizeof(cache_header));
}
while (true) {
try {
{
char header_buff[total_header_size];
std::ifstream hs(_cache_file_path.generic_string(), std::ifstream::binary);
hs.read(header_buff, sizeof(header_buff));
EOS_ASSERT(!hs.fail(), bad_database_version_exception, "failed to read code cache header");
memcpy((char*)&cache_header, header_buff + header_offset, sizeof(cache_header));
}

EOS_ASSERT(cache_header.id == header_id, bad_database_version_exception, "existing EOS VM OC code cache not compatible with this version");
EOS_ASSERT(!cache_header.dirty, database_exception, "code cache is dirty");
EOS_ASSERT(cache_header.id == header_id, bad_database_version_exception, "existing EOS VM OC code cache not compatible with this version");
EOS_ASSERT(!cache_header.dirty, database_exception, "code cache is dirty");
break;
} catch (const fc::exception&) {
if (created_file)
throw;

ilog("EOS VM optimized Compiler code cache corrupt, recreating");
create_code_cache_file();
}
}

set_on_disk_region_dirty(true);

Expand Down

0 comments on commit d6882dd

Please sign in to comment.