Better error handling

This commit is contained in:
patrick96 2021-09-11 11:46:37 +02:00 committed by Patrick Ziegler
parent 53ce1ae414
commit 9d9fe8bffb
5 changed files with 54 additions and 27 deletions

View File

@ -53,6 +53,8 @@ class controller
bool enqueue(event&& evt);
bool enqueue(string&& input_data);
void stop(bool reload);
void signal_handler(int signum);
void conn_cb(int status, int events);

View File

@ -5,6 +5,7 @@
#include <stdexcept>
#include "common.hpp"
#include "components/logger.hpp"
POLYBAR_NS
@ -12,11 +13,13 @@ POLYBAR_NS
* Runs any libuv function with an integer error code return value and throws an
* exception on error.
*/
#define UV(fun, ...) \
int res = fun(__VA_ARGS__); \
if (res < 0) { \
throw std::runtime_error("libuv error for '" #fun "': "s + uv_strerror(res)); \
}
#define UV(fun, ...) \
do { \
int res = fun(__VA_ARGS__); \
if (res < 0) { \
throw std::runtime_error("libuv error for '" #fun "': "s + uv_strerror(res)); \
} \
} while (0);
template <class H, class... Args>
struct cb_helper {
@ -51,7 +54,7 @@ struct SignalHandle : public UVHandle<uv_signal_t, int> {
};
struct PollHandle : public UVHandle<uv_poll_t, int, int> {
// TODO wrap callback and handle negative status
// TODO wrap callback and handle status
PollHandle(uv_loop_t* loop, int fd, std::function<void(int, int)> fun) : UVHandle(fun) {
UV(uv_poll_init, loop, handle.get(), fd);
}

View File

@ -27,6 +27,13 @@ namespace {
return !(id == static_cast<int>(type));
}
/**
* Create QUIT event
*/
inline event make_none_evt() {
return event{static_cast<int>(event_type::NONE)};
}
/**
* Create QUIT event
*/

View File

@ -134,6 +134,7 @@ bool controller::run(bool writeback, string snapshot_dst) {
read_events();
if (m_event_thread.joinable()) {
m_log.info("Joining event thread");
m_event_thread.join();
}
@ -153,9 +154,6 @@ bool controller::enqueue(event&& evt) {
m_log.warn("Failed to enqueue event");
return false;
}
// if (write(g_eventpipe[PIPE_WRITE], " ", 1) == -1) {
// m_log.err("Failed to write to eventpipe (reason: %s)", strerror(errno));
// }
return true;
}
@ -172,17 +170,28 @@ bool controller::enqueue(string&& input_data) {
return false;
}
void controller::conn_cb(int, int) {
// TODO handle negative status
if (m_connection.connection_has_error()) {
g_terminate = 1;
g_reload = 0;
eloop->stop();
void controller::stop(bool reload) {
g_terminate = 1;
g_reload = reload;
eloop->stop();
}
void controller::conn_cb(int status, int) {
if (status < 0) {
// TODO Should we stop polling here?
m_log.err("libuv error while polling X connection: %s", uv_strerror(status));
return;
}
int xcb_error = m_connection.connection_has_error();
if ((xcb_error = m_connection.connection_has_error()) > 0) {
m_log.err("X connection error, terminating... (what: %s)", m_connection.error_str(xcb_error));
stop(false);
return;
}
shared_ptr<xcb_generic_event_t> evt{};
while ((evt = shared_ptr<xcb_generic_event_t>(xcb_poll_for_event(m_connection), free)) != nullptr) {
if ((evt = shared_ptr<xcb_generic_event_t>(xcb_poll_for_event(m_connection), free)) != nullptr) {
try {
m_connection.dispatch_event(evt);
} catch (xpp::connection_error& err) {
@ -190,6 +199,12 @@ void controller::conn_cb(int, int) {
} catch (const exception& err) {
m_log.err("Error in X event loop: %s", err.what());
}
} else {
if ((xcb_error = m_connection.connection_has_error()) > 0) {
m_log.err("X connection error, terminating... (what: %s)", m_connection.error_str(xcb_error));
stop(false);
return;
}
}
}
@ -200,19 +215,15 @@ void controller::ipc_cb(string buf) {
void controller::signal_handler(int signum) {
m_log.notice("Received signal SIG%s", sigabbrev_np(signum));
g_terminate = 1;
g_reload = (signum == SIGUSR1);
eloop->stop();
stop(signum == SIGUSR1);
}
void controller::confwatch_handler(const char*, int, int) {
g_terminate = 1;
g_reload = 1;
eloop->stop();
void controller::confwatch_handler(const char* filename, int, int) {
m_log.notice("Watched config file changed %s", filename);
stop(true);
}
static void ipc_alloc_cb(uv_handle_t*, size_t, uv_buf_t* buf) {
// TODO handle alloc error
buf->base = new char[BUFSIZ];
buf->len = BUFSIZ;
}
@ -271,10 +282,14 @@ void controller::read_events() {
eloop->run();
} catch (const exception& err) {
m_log.err("Fatal Error in eventloop: %s", err.what());
g_terminate = 1;
eloop->stop();
stop(false);
}
// Notify event queue so that it stops
enqueue(make_none_evt());
m_log.info("Eventloop finished");
eloop.reset();
}

View File

@ -116,7 +116,7 @@ int main(int argc, char** argv) {
// against pid if one was defined
for (auto&& channel : pipes) {
try {
file_descriptor fd(channel, O_WRONLY | O_NONBLOCK);
file_descriptor fd(channel, O_WRONLY | O_NONBLOCK, true);
string payload{ipc_type + ':' + ipc_payload};
if (write(fd, payload.c_str(), payload.size()) != -1) {
display("Successfully wrote \"" + payload + "\" to \"" + channel + "\"");