Skip to content

Commit

Permalink
Use source version to prevent reloading the same binary
Browse files Browse the repository at this point in the history
  • Loading branch information
fwsGonzo committed Oct 20, 2024
1 parent 970b14b commit 945848b
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 16 deletions.
7 changes: 4 additions & 3 deletions src/elf/script_elf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void ELFScript::_bind_methods() {
}

Sandbox *ELFScript::get_sandbox_for(Object *p_for_object) const {
for (ELFScriptInstance *instance : instances) {
for (ELFScriptInstance *instance : this->instances) {
if (instance->get_owner() == p_for_object) {
auto [sandbox, auto_created] = instance->get_sandbox();
return sandbox;
Expand All @@ -29,7 +29,7 @@ Sandbox *ELFScript::get_sandbox_for(Object *p_for_object) const {

Array ELFScript::get_sandboxes() const {
Array result;
for (ELFScriptInstance *instance : instances) {
for (ELFScriptInstance *instance : this->instances) {
result.push_back(instance->get_owner());
}
return result;
Expand Down Expand Up @@ -125,7 +125,8 @@ String ELFScript::_get_source_code() const {
void ELFScript::_set_source_code(const String &p_code) {
}
Error ELFScript::_reload(bool p_keep_state) {
this->set_file(path);
this->source_version++;
this->set_file(this->path);
return Error::OK;
}
TypedArray<Dictionary> ELFScript::_get_documentation() const {
Expand Down
5 changes: 4 additions & 1 deletion src/elf/script_elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class ELFScript : public ScriptExtension {
PackedByteArray source_code;
String global_name;
String path;
int source_version = 0;
int elf_api_version;
String elf_programming_language;

Expand All @@ -28,8 +29,10 @@ class ELFScript : public ScriptExtension {
public:
PackedStringArray functions;
String get_elf_programming_language() const;
int get_elf_api_version() const { return elf_api_version; }
int get_elf_api_version() const noexcept { return elf_api_version; }
int get_source_version() const noexcept { return source_version; }
String get_dockerized_program_path() const;
const String &get_path() const noexcept { return path; }

/// @brief Retrieve a Sandbox instance based on a given owner object.
/// @param p_for_object The owner object.
Expand Down
27 changes: 16 additions & 11 deletions src/sandbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,15 @@ Sandbox::~Sandbox() {
}

void Sandbox::set_program(Ref<ELFScript> program) {
// Avoid reloading the same program
if (program.is_valid() && this->m_program_data == program) {
if (this->m_source_version == program->get_source_version()) {
return;
}
} else {
this->m_source_version = -1;
}

// Try to retain Sandboxed properties
std::vector<SandboxProperty> properties = std::move(this->m_properties);
std::vector<Variant> property_values;
Expand All @@ -230,7 +239,9 @@ void Sandbox::set_program(Ref<ELFScript> program) {
this->full_reset();
}

this->load(&m_program_data->get_content());
if (this->load(&m_program_data->get_content())) {
this->m_source_version = this->m_program_data->get_source_version();
}

// Restore Sandboxed properties by comparing the new program's properties
// with the old ones, then comparing the type. If the property is found,
Expand Down Expand Up @@ -259,18 +270,11 @@ void Sandbox::load_buffer(const PackedByteArray &buffer) {
bool Sandbox::has_program_loaded() const {
return !machine().memory.binary().empty();
}
void Sandbox::load(const PackedByteArray *buffer, const std::vector<std::string> *argv_ptr) {
bool Sandbox::load(const PackedByteArray *buffer, const std::vector<std::string> *argv_ptr) {
if (buffer == nullptr || buffer->is_empty()) {
ERR_PRINT("Empty binary, cannot load program.");
this->reset_machine();
return;
}
// If the binary sizes match, let's see if the binary is the exact same
if (this->m_machine != nullptr && buffer->size() == this->m_machine->memory.binary().size()) {
if (std::memcmp(buffer->ptr(), this->m_machine->memory.binary().data(), buffer->size()) == 0) {
// Binary is the same, no need to reload
return;
}
return false;
}
const std::string_view binary_view = std::string_view{ (const char *)buffer->ptr(), static_cast<size_t>(buffer->size()) };

Expand Down Expand Up @@ -303,7 +307,7 @@ void Sandbox::load(const PackedByteArray *buffer, const std::vector<std::string>
} catch (const std::exception &e) {
ERR_PRINT(("Sandbox construction exception: " + std::string(e.what())).c_str());
this->m_machine = new machine_t{};
return;
return false;
}

/** Now we can process symbols, backtraces etc. */
Expand Down Expand Up @@ -353,6 +357,7 @@ void Sandbox::load(const PackedByteArray *buffer, const std::vector<std::string>
double startup_time = (startup_t1 - startup_t0) / 1e6;
m_accumulated_startup_time += startup_time;
//fprintf(stderr, "Sandbox startup time: %.3f seconds\n", startup_time);
return true;
}

Variant Sandbox::vmcall_address(gaddr_t address, const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
Expand Down
3 changes: 2 additions & 1 deletion src/sandbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ class Sandbox : public Node {
void constructor_initialize();
void full_reset();
void reset_machine();
void load(const PackedByteArray *vbuf, const std::vector<std::string> *argv = nullptr);
bool load(const PackedByteArray *vbuf, const std::vector<std::string> *argv = nullptr);
void read_program_properties(bool editor) const;
void handle_exception(gaddr_t);
void handle_timeout(gaddr_t);
Expand Down Expand Up @@ -482,6 +482,7 @@ class Sandbox : public Node {

Ref<ELFScript> m_program_data;
PackedByteArray m_program_bytes;
int m_source_version = -1;

// Stats
unsigned m_timeouts = 0;
Expand Down

0 comments on commit 945848b

Please sign in to comment.