Better error handling
This commit is contained in:
parent
53ce1ae414
commit
9d9fe8bffb
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 + "\"");
|
||||||
|
Loading…
Reference in New Issue
Block a user