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(event&& evt);
bool enqueue(string&& input_data); bool enqueue(string&& input_data);
void stop(bool reload);
void signal_handler(int signum); void signal_handler(int signum);
void conn_cb(int status, int events); void conn_cb(int status, int events);

View File

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

View File

@ -27,6 +27,13 @@ namespace {
return !(id == static_cast<int>(type)); 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 * Create QUIT event
*/ */

View File

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

View File

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