Skip to content

Commit

Permalink
Make missing critical packages trip emergency mode
Browse files Browse the repository at this point in the history
If zero packages for a crucial hook are loaded, this throws an exception which is caught and trips the emergency mode. This also happens when init.be for a package is missing.
  • Loading branch information
alufers committed May 4, 2024
1 parent b150842 commit 6698878
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 14 deletions.
9 changes: 6 additions & 3 deletions src/core/main/app/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,19 +121,22 @@ void Core::initialize() {
try {

// Load system packages
this->pkgLoader->loadWithHook("system");
this->pkgLoader->loadWithHook("system", true);
this->pkgLoader->loadWithHook("plugin");

#ifdef ESP_PLATFORM
this->pkgLoader->loadWithHook("plugin_esp32");
this->pkgLoader->loadWithHook("platform_esp32");
this->pkgLoader->loadWithHook("platform_esp32", true);
#else
this->pkgLoader->loadWithHook("platform_desktop");
this->pkgLoader->loadWithHook("platform_desktop", true);
#endif

} catch (berry::BerryErrorException& e) {
this->ctx->emergencyMode->trip(EmergencyModeReason::BERRY_INIT_ERROR,
e.what());
} catch(PackageLoaderFileNotFoundException& e) {
this->ctx->emergencyMode->trip(EmergencyModeReason::LOADING_BERRY_HOOK_FAILED,
e.what());
}

// Initialize HTTP
Expand Down
4 changes: 1 addition & 3 deletions src/core/main/app/EmergencyMode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ extern unsigned int emergencyModeHtml_len;
} // namespace euph

EmergencyMode::EmergencyMode() {
EUPH_LOG(info, "EmergencyMode",
"std::atomic<EmergencyModeReason>::is_lock_free() = %d",
std::atomic<EmergencyModeReason>{}.is_lock_free());
}

bool EmergencyMode::isActive() const {
Expand Down Expand Up @@ -74,6 +71,7 @@ std::string EmergencyMode::getReasonString(EmergencyModeReason reason) {
CASE_RETURN_STR(NOT_ACTIVE);
CASE_RETURN_STR(BERRY_INIT_ERROR);
CASE_RETURN_STR(MANUAL_TRIP);
CASE_RETURN_STR(LOADING_BERRY_HOOK_FAILED);
}

return "__FIXME_UNKNOWN_ENUM_VALUE__";
Expand Down
13 changes: 12 additions & 1 deletion src/core/main/app/PackageLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ void PackageLoader::loadValidPackages() {
}
}

void PackageLoader::loadWithHook(const std::string& hook) {
void PackageLoader::loadWithHook(const std::string& hook, bool packageRequired) {
EUPH_LOG(info, TAG, "Loading packages with hook: %s", hook.c_str());
bool found = false;
for (auto pkg : this->packages) {
if (pkg.initHook == hook) {
EUPH_LOG(info, TAG, "Loading package: %s", pkg.name.c_str());
Expand All @@ -66,10 +67,20 @@ void PackageLoader::loadWithHook(const std::string& hook) {

// Read init code file
std::ifstream initCodeFile(initPath);
if (initCodeFile.fail()) {
EUPH_LOG(error, TAG, "Failed to load berry script: %s", initPath.c_str());
throw PackageLoaderFileNotFoundException("Failed to load berry script: " + initPath);
}
std::stringstream initCodeBuffer;
initCodeBuffer << initCodeFile.rdbuf();

ctx->vm->execute_string(initCodeBuffer.str(), initPath);
found = true;
}
}

if (packageRequired && !found) {
EUPH_LOG(error, TAG, "No packages found for hook: %s, but a package is required.", hook.c_str());
throw PackageLoaderFileNotFoundException("No packages found for hook: " + hook + ", but a package is required.");
}
}
9 changes: 9 additions & 0 deletions src/core/main/app/emergency.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@
font-size: 2rem;
color: #333;
}
code {
display: block;
white-space: pre-wrap;
background-color: #f0f0f0;
padding: 1rem;
border-radius: 5px;
font-size: 0.9rem;
overflow-x: auto;
}
</style>
</head>
<body>
Expand Down
13 changes: 9 additions & 4 deletions src/core/main/app/include/EmergencyMode.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#pragma once

#include <atomic>
#include <memory>
#include <mutex>
#include <nlohmann/json.hpp>
#include <shared_mutex>
#include <string>
#include <atomic>
#include <shared_mutex>
#include "civetweb.h"
#include <nlohmann/json.hpp>

namespace euph {

Expand All @@ -27,10 +26,16 @@ enum class EmergencyModeReason {
*/
BERRY_INIT_ERROR = 1,

/**
* @brief Could not load packages for a given berry hook.
*
*/
LOADING_BERRY_HOOK_FAILED = 2,

/**
* @brief Emeregency mode tripped manually by the user.
*/
MANUAL_TRIP = 2,
MANUAL_TRIP = 3,
};

/**
Expand Down
23 changes: 20 additions & 3 deletions src/core/main/app/include/PackageLoader.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
#pragma once

#include <ghc_filesystem.h>
#include <fmt/core.h>
#include <ghc_filesystem.h>
#include <exception>
#include <fstream>
#include <memory>
#include <string>

#include <nlohmann/json.hpp>
#include "EuphContext.h"

namespace euph {

class PackageLoaderFileNotFoundException : public std::exception {
public:
PackageLoaderFileNotFoundException(const std::string& message)
: message(message) {}

const char* what() const noexcept override { return message.c_str(); }

private:
std::string message;
};

class PackageLoader {
public:
PackageLoader(std::shared_ptr<euph::Context> ctx);
Expand All @@ -29,9 +43,12 @@ class PackageLoader {
/**
* @brief Loads a package under a given hook into the VM
*
* @throws PackageLoaderFileNotFoundException if the package file is not found
*
* @param hook the hook to load, one of the 'validHooks' vector
* @param packageRequired if true, throws an exception if zero packages for this hook were loaded
*/
void loadWithHook(const std::string& hook);
void loadWithHook(const std::string& hook, bool packageRequired = false);

private:
const std::string TAG = "package-loader";
Expand All @@ -40,4 +57,4 @@ class PackageLoader {

std::vector<std::string> validHooks = {"system", "plugin"};
};
} // namespace euph
} // namespace euph

0 comments on commit 6698878

Please sign in to comment.