diff --git a/include/components/controller.hpp b/include/components/controller.hpp index b3dcf28d..4370d3c3 100644 --- a/include/components/controller.hpp +++ b/include/components/controller.hpp @@ -3,8 +3,8 @@ #include #include -#include #include +#include #include "common.hpp" #include "components/eventloop.hpp" diff --git a/include/components/eventloop.hpp b/include/components/eventloop.hpp index 9f3cdf40..89694e84 100644 --- a/include/components/eventloop.hpp +++ b/include/components/eventloop.hpp @@ -13,12 +13,13 @@ POLYBAR_NS * Runs any libuv function with an integer error code return value and throws an * exception on error. */ -#define UV(fun, ...) \ - do { \ - 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( \ + __FILE__ ":"s + std::to_string(__LINE__) + ": libuv error for '" #fun "': "s + uv_strerror(res)); \ + } \ } while (0); template @@ -31,6 +32,10 @@ struct cb_helper { } }; +/** + * \tparam H Type of the handle + * \tparam I Type of the handle passed to the callback. Often the same as H, but not always (e.g. uv_read_start) + */ template struct UVHandleGeneric { UVHandleGeneric(std::function fun) { @@ -81,43 +86,45 @@ struct FSEventHandle : public UVHandle { }; struct PipeHandle : public UVHandleGeneric { - PipeHandle(uv_loop_t* loop, std::function fun) - : UVHandleGeneric([&](ssize_t nread, const uv_buf_t* buf) { - if (nread > 0) { - string payload = string(buf->base, nread); - logger::make().notice("Bytes read: %d: '%s'", nread, payload); - fun(std::move(payload)); - } else if (nread < 0) { - if (nread != UV_EOF) { - logger::make().err("Read error: %s", uv_err_name(nread)); - uv_close((uv_handle_t*)handle.get(), nullptr); - } else { - UV( - uv_read_start, (uv_stream_t*)handle.get(), - [](uv_handle_t*, size_t, uv_buf_t* buf) { - buf->base = new char[BUFSIZ]; - buf->len = BUFSIZ; - }, - &cb.callback); - } - } + std::function func; - if (buf->base) { - delete[] buf->base; - } - }) { + int fd; + + PipeHandle(uv_loop_t* loop, std::function fun) + : UVHandleGeneric([&](ssize_t nread, const uv_buf_t* buf) { read_cb(nread, buf); }), func(fun) { UV(uv_pipe_init, loop, handle.get(), false); } void start(int fd) { + this->fd = fd; UV(uv_pipe_open, handle.get(), fd); - UV( - uv_read_start, (uv_stream_t*)handle.get(), - [](uv_handle_t*, size_t, uv_buf_t* buf) { - buf->base = new char[BUFSIZ]; - buf->len = BUFSIZ; - }, - &cb.callback); + UV(uv_read_start, (uv_stream_t*)handle.get(), alloc_cb, &cb.callback); + } + + static void alloc_cb(uv_handle_t*, size_t, uv_buf_t* buf) { + buf->base = new char[BUFSIZ]; + buf->len = BUFSIZ; + } + + void read_cb(ssize_t nread, const uv_buf_t* buf) { + auto log = logger::make(); + if (nread > 0) { + string payload = string(buf->base, nread); + log.notice("Bytes read: %d: '%s'", nread, payload); + func(payload); + } else if (nread < 0) { + if (nread != UV_EOF) { + log.err("Read error: %s", uv_err_name(nread)); + uv_close((uv_handle_t*)handle.get(), nullptr); + } else { + // TODO this causes constant EOFs + start(this->fd); + } + } + + if (buf->base) { + delete[] buf->base; + } } }; diff --git a/src/components/controller.cpp b/src/components/controller.cpp index 0f7a32f7..18d52fc9 100644 --- a/src/components/controller.cpp +++ b/src/components/controller.cpp @@ -237,30 +237,6 @@ void controller::notifier_handler() { } } -static void ipc_alloc_cb(uv_handle_t*, size_t, uv_buf_t* buf) { - buf->base = new char[BUFSIZ]; - buf->len = BUFSIZ; -} - -static void ipc_read_cb_wrapper(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { - if (nread > 0) { - string payload = string(buf->base, nread); - logger::make().notice("Bytes read: %d: '%s'", nread, payload); - static_cast(stream->data)->ipc_cb(std::move(payload)); - } else if (nread < 0) { - if (nread != UV_EOF) { - fprintf(stderr, "Read error %s\n", uv_err_name(nread)); - uv_close((uv_handle_t*)stream, nullptr); - } else { - uv_read_start(stream, ipc_alloc_cb, ipc_read_cb_wrapper); - } - } - - if (buf->base) { - delete[] buf->base; - } -} - static void notifier_cb_wrapper(uv_async_t* handle) { static_cast(handle->data)->notifier_handler(); } @@ -284,7 +260,7 @@ void controller::read_events(bool confwatch) { m_bar->start(); } - auto ipc_handle = std::unique_ptr(nullptr); + auto ipc_handle = std::unique_ptr(nullptr); auto screenshot_timer_handle = std::unique_ptr(nullptr); try { @@ -304,11 +280,8 @@ void controller::read_events(bool confwatch) { } if (m_ipc) { - ipc_handle = std::make_unique(); - UV(uv_pipe_init, loop, ipc_handle.get(), false); - ipc_handle->data = this; - UV(uv_pipe_open, ipc_handle.get(), m_ipc->get_file_descriptor()); - UV(uv_read_start, (uv_stream_t*)ipc_handle.get(), ipc_alloc_cb, ipc_read_cb_wrapper); + ipc_handle = std::make_unique(loop, [this](const string payload) { ipc_cb(payload); }); + ipc_handle->start(m_ipc->get_file_descriptor()); } m_notifier = std::make_unique(); diff --git a/src/components/eventloop.cpp b/src/components/eventloop.cpp index da7dad97..c70254bc 100644 --- a/src/components/eventloop.cpp +++ b/src/components/eventloop.cpp @@ -30,7 +30,7 @@ eventloop::~eventloop() { close_loop(m_loop.get()); UV(uv_loop_close, m_loop.get()); } catch (const std::exception& e) { - // TODO log error + logger::make().err("%s", e.what()); } m_loop.reset();