slightly more robust error handling
This commit is contained in:
parent
8196f711bc
commit
ee1ef5906d
|
@ -8,12 +8,15 @@ namespace nanosm {
|
||||||
epollFd = epoll_create1(EPOLL_CLOEXEC);
|
epollFd = epoll_create1(EPOLL_CLOEXEC);
|
||||||
|
|
||||||
if(epollFd == -1) {
|
if(epollFd == -1) {
|
||||||
perror("You Banned From Epoll, Rules");
|
throw std::system_error(std::make_error_code(static_cast<std::errc>(errno)));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EventLoop::~EventLoop() {
|
EventLoop::~EventLoop() {
|
||||||
close(epollFd);
|
if(epollFd == -1) {
|
||||||
|
close(epollFd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventLoop::Post(PostFn func) {
|
void EventLoop::Post(PostFn func) {
|
||||||
|
@ -56,25 +59,27 @@ namespace nanosm {
|
||||||
UniqueArray<epoll_event> events { 16 };
|
UniqueArray<epoll_event> events { 16 };
|
||||||
|
|
||||||
while(!shouldStop) {
|
while(!shouldStop) {
|
||||||
auto nevents = epoll_wait(epollFd, events.Get(), events.Size(), 10);
|
// The timeout here is larger than it probably would be if e.g: this was dealing with sockets,
|
||||||
if(nevents == -1) {
|
// mostly because nanosm is designed to only really use CPU if it has to (i.e: a process died, timer elapsed, etc)
|
||||||
perror("epoll_wait");
|
auto nrEvents = epoll_wait(epollFd, events.Get(), events.Size(), 50);
|
||||||
break;
|
if(nrEvents == -1) {
|
||||||
|
throw std::system_error(std::make_error_code(static_cast<std::errc>(errno)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// All OK, let's check for events now
|
if(nrEvents != 0) {
|
||||||
|
for(int i = 0; i < nrEvents; ++i) {
|
||||||
for(int i = 0; i < nevents; ++i) {
|
for(auto pollable : ioObjects) {
|
||||||
for(auto pollable : ioObjects) {
|
if(auto fd = pollable->GetFD(); fd != -1) {
|
||||||
if(auto fd = pollable->GetFD(); fd != -1) {
|
// Signal any events that occur for this
|
||||||
// Signal any events that occur for this
|
if(events[i].data.fd == fd)
|
||||||
if(events[i].data.fd == fd)
|
pollable->OnReady(events[i].events);
|
||||||
pollable->OnReady(events[i].events);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the topmost callback once every event loop iteration.
|
// Run the topmost callback once every event loop iteration,
|
||||||
|
// even if epoll never signaled readiness.
|
||||||
if(!postCallbacks.empty()) {
|
if(!postCallbacks.empty()) {
|
||||||
auto& frontCallback = postCallbacks.front();
|
auto& frontCallback = postCallbacks.front();
|
||||||
frontCallback();
|
frontCallback();
|
||||||
|
|
|
@ -7,8 +7,9 @@ namespace nanosm {
|
||||||
Timer::Timer(nanosm::EventLoop& ev)
|
Timer::Timer(nanosm::EventLoop& ev)
|
||||||
: nanosm::EventLoop::IoObject(ev) {
|
: nanosm::EventLoop::IoObject(ev) {
|
||||||
timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
|
timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
|
||||||
if(timerFd < 0)
|
if(timerFd < 0) {
|
||||||
perror("timerfd_create");
|
throw std::system_error(std::make_error_code(static_cast<std::errc>(errno)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer::~Timer() {
|
Timer::~Timer() {
|
||||||
|
|
86
src/main.cpp
86
src/main.cpp
|
@ -2,6 +2,7 @@
|
||||||
#include <format>
|
#include <format>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <system_error>
|
||||||
#include <toml++/toml.hpp>
|
#include <toml++/toml.hpp>
|
||||||
|
|
||||||
#include "EventLoop.hpp"
|
#include "EventLoop.hpp"
|
||||||
|
@ -82,7 +83,12 @@ struct NanoSm {
|
||||||
this->SpawnAllApps();
|
this->SpawnAllApps();
|
||||||
});
|
});
|
||||||
|
|
||||||
ev.Run();
|
try {
|
||||||
|
ev.Run();
|
||||||
|
} catch(std::exception& ec) {
|
||||||
|
nanosm::log::Error("NanoSm", "Unhandled exception in event loop: {}", ec.what());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,51 +111,55 @@ fs::path GetConfigPath() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
NanoSm nanosm;
|
|
||||||
|
|
||||||
auto configPath = GetConfigPath();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto tomlTable = toml::parse_file(configPath.string());
|
NanoSm nanosm;
|
||||||
|
|
||||||
if(tomlTable["nanosm"].is_table() && tomlTable["nanosm"]["apps"].is_table()) {
|
auto configPath = GetConfigPath();
|
||||||
auto restartptr = tomlTable["nanosm"]["restart-time"].as_integer();
|
|
||||||
|
|
||||||
if(!restartptr) {
|
try {
|
||||||
nanosm::log::Warn("NanoSm", "No restart time provided in nanosm.toml. Defaulting to 1 second.");
|
auto tomlTable = toml::parse_file(configPath.string());
|
||||||
nanosm.SetRestartTime(1);
|
|
||||||
|
if(tomlTable["nanosm"].is_table() && tomlTable["nanosm"]["apps"].is_table()) {
|
||||||
|
auto restartptr = tomlTable["nanosm"]["restart-time"].as_integer();
|
||||||
|
|
||||||
|
if(!restartptr) {
|
||||||
|
nanosm::log::Warn("NanoSm", "No restart time provided in nanosm.toml. Defaulting to 1 second.");
|
||||||
|
nanosm.SetRestartTime(1);
|
||||||
|
} else {
|
||||||
|
nanosm.SetRestartTime(static_cast<u32>(restartptr->get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto [key, value] : *tomlTable["nanosm"]["apps"].as_table()) {
|
||||||
|
if(!value.is_table()) {
|
||||||
|
nanosm::log::Warn("NanoSm", "Ignoring invalid app \"{}\" in configuration file", key.str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& appTable = *value.as_table();
|
||||||
|
|
||||||
|
if(!appTable.get("command")->is_string()) {
|
||||||
|
nanosm::log::Warn("NanoSm", "Ignoring invalid app \"{}\" in configuration file", key.str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto cmd = appTable.get("command")->as_string()->get();
|
||||||
|
|
||||||
|
nanosm::log::Info("NanoSm", "Adding app \"{}\" with command \"{}\"", key.str(), cmd);
|
||||||
|
|
||||||
|
nanosm.AddApp(std::string(key.data(), key.length()), std::string(cmd.data(), cmd.length()));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
nanosm.SetRestartTime(static_cast<u32>(restartptr->get()));
|
nanosm::log::Error("NanoSm", "Configuration file {} doesn't have required values. Exiting with failure.", configPath.string());
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto [key, value] : *tomlTable["nanosm"]["apps"].as_table()) {
|
return nanosm.Run();
|
||||||
if(!value.is_table()) {
|
} catch(toml::parse_error& pe) {
|
||||||
nanosm::log::Warn("NanoSm", "Ignoring invalid app \"{}\" in configuration file", key.str());
|
std::fprintf(stderr, "Error parsing config file \"%s\": %s\n", configPath.c_str(), pe.description().data());
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& appTable = *value.as_table();
|
|
||||||
|
|
||||||
if(!appTable.get("command")->is_string()) {
|
|
||||||
nanosm::log::Warn("NanoSm", "Ignoring invalid app \"{}\" in configuration file", key.str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto cmd = appTable.get("command")->as_string()->get();
|
|
||||||
|
|
||||||
nanosm::log::Info("NanoSm", "Adding app \"{}\" with command \"{}\"", key.str(), cmd);
|
|
||||||
|
|
||||||
nanosm.AddApp(std::string(key.data(), key.length()), std::string(cmd.data(), cmd.length()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
nanosm::log::Error("NanoSm", "Configuration file {} doesn't have required values. Exiting with failure.", configPath.string());
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
} catch(std::exception& ec) {
|
||||||
} catch(toml::parse_error& pe) {
|
nanosm::log::Error("NanoSm", "Error initalizing NanoSm: {}", ec.what());
|
||||||
std::fprintf(stderr, "Error parsing config file \"%s\": %s\n", configPath.c_str(), pe.description().data());
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nanosm.Run();
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue