diff --git a/include/components/controller.hpp b/include/components/controller.hpp index e8d84c5b..99f25942 100644 --- a/include/components/controller.hpp +++ b/include/components/controller.hpp @@ -5,6 +5,7 @@ #include #include "common.hpp" +#include "components/eventloop.hpp" #include "components/types.hpp" #include "events/signal_fwd.hpp" #include "events/signal_receiver.hpp" @@ -53,7 +54,7 @@ class controller bool enqueue(string&& input_data); void conn_cb(int status, int events); - void ipc_cb(int status, int events); + void ipc_cb(string buf); protected: void read_events(); @@ -87,6 +88,8 @@ class controller unique_ptr m_ipc; unique_ptr m_confwatch; + eventloop eloop; + /** * \brief State flag */ diff --git a/include/components/eventloop.hpp b/include/components/eventloop.hpp new file mode 100644 index 00000000..bffe88e1 --- /dev/null +++ b/include/components/eventloop.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include "common.hpp" + +POLYBAR_NS + +class eventloop { + public: + eventloop(); + ~eventloop(); + + void run(); + + void stop(); + + /** + * TODO remove + */ + uv_loop_t* get() const { + return m_loop.get(); + } + + private: + std::unique_ptr m_loop{nullptr}; +}; + +POLYBAR_NS_END diff --git a/include/components/ipc.hpp b/include/components/ipc.hpp index 6b09882a..e551d789 100644 --- a/include/components/ipc.hpp +++ b/include/components/ipc.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "common.hpp" #include "settings.hpp" #include "utils/concurrency.hpp" @@ -32,7 +34,7 @@ class ipc { explicit ipc(signal_emitter& emitter, const logger& logger); ~ipc(); - void receive_message(); + void receive_message(string buf); int get_file_descriptor() const; private: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3200d3a4..77d30408 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -67,6 +67,7 @@ if(BUILD_LIBPOLY) ${src_dir}/components/renderer.cpp ${src_dir}/components/screen.cpp ${src_dir}/components/taskqueue.cpp + ${src_dir}/components/eventloop.cpp ${src_dir}/drawtypes/animation.cpp ${src_dir}/drawtypes/iconset.cpp diff --git a/src/components/controller.cpp b/src/components/controller.cpp index d9baebac..21c8ee88 100644 --- a/src/components/controller.cpp +++ b/src/components/controller.cpp @@ -8,6 +8,7 @@ #include "components/bar.hpp" #include "components/builder.hpp" #include "components/config.hpp" +#include "components/eventloop.hpp" #include "components/ipc.hpp" #include "components/logger.hpp" #include "components/types.hpp" @@ -172,13 +173,13 @@ bool controller::enqueue(string&& input_data) { return false; } -void controller::conn_cb(int status, int events) { +void controller::conn_cb(int, int) { // TODO handle negative status if (m_connection.connection_has_error()) { g_terminate = 1; g_reload = 0; - uv_stop(uv_default_loop()); + eloop.stop(); return; } @@ -194,31 +195,52 @@ void controller::conn_cb(int status, int events) { } } -void controller::ipc_cb(int status, int events) { - // TODO handle negative status - m_ipc->receive_message(); +void controller::ipc_cb(string buf) { + // TODO handle messages sent in multiple parts. + m_ipc->receive_message(buf); } static void conn_cb_wrapper(uv_poll_t* handle, int status, int events) { static_cast(handle->data)->conn_cb(status, events); } -static void ipc_cb_wrapper(uv_poll_t* handle, int status, int events) { - static_cast(handle->data)->ipc_cb(status, events); -} - static void signal_cb_wrapper(uv_signal_t* handle, int signum) { g_terminate = 1; g_reload = (signum == SIGUSR1); - uv_stop(handle->loop); + static_cast(handle->loop->data)->stop(); } -static void confwatch_cb_wrapper(uv_fs_event_t* handle, const char* fname, int events, int status) { +static void confwatch_cb_wrapper(uv_fs_event_t* handle, const char* fname, int, int) { // TODO handle error std::cout << fname << std::endl; g_terminate = 1; g_reload = 1; - uv_stop(handle->loop); + static_cast(handle->loop->data)->stop(); +} + +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; +} + +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; + } } /** @@ -227,7 +249,7 @@ static void confwatch_cb_wrapper(uv_fs_event_t* handle, const char* fname, int e void controller::read_events() { m_log.info("Entering event loop (thread-id=%lu)", this_thread::get_id()); - auto loop = uv_default_loop(); + auto loop = eloop.get(); auto conn_handle = std::make_unique(); uv_poll_init(loop, conn_handle.get(), m_connection.get_file_descriptor()); @@ -256,17 +278,17 @@ void controller::read_events() { uv_fs_event_start(conf_handle.get(), confwatch_cb_wrapper, m_confwatch->path().c_str(), 0); } - auto ipc_handle = std::unique_ptr(nullptr); + auto ipc_handle = std::unique_ptr(nullptr); if (m_ipc) { - ipc_handle = std::make_unique(); - uv_poll_init(loop, ipc_handle.get(), m_ipc->get_file_descriptor()); + ipc_handle = std::make_unique(); + uv_pipe_init(loop, ipc_handle.get(), false); ipc_handle->data = this; - uv_poll_start(ipc_handle.get(), UV_READABLE, ipc_cb_wrapper); + uv_pipe_open(ipc_handle.get(), m_ipc->get_file_descriptor()); + uv_read_start((uv_stream_t*)ipc_handle.get(), ipc_alloc_cb, ipc_read_cb_wrapper); } - uv_run(loop, UV_RUN_DEFAULT); - uv_loop_close(loop); + eloop.run(); } /** diff --git a/src/components/eventloop.cpp b/src/components/eventloop.cpp new file mode 100644 index 00000000..99e2e35e --- /dev/null +++ b/src/components/eventloop.cpp @@ -0,0 +1,30 @@ +#include "components/eventloop.hpp" + +POLYBAR_NS + +eventloop::eventloop() { + m_loop = std::make_unique(); + uv_loop_init(m_loop.get()); + // TODO handle return value + + m_loop->data = this; +} + +eventloop::~eventloop() { + if (m_loop) { + uv_loop_close(m_loop.get()); + // TODO handle return value + } +} + +void eventloop::run() { + uv_run(m_loop.get(), UV_RUN_DEFAULT); + // TODO handle return value +} + +void eventloop::stop() { + uv_stop(m_loop.get()); + // TODO handle return value +} + +POLYBAR_NS_END diff --git a/src/components/ipc.cpp b/src/components/ipc.cpp index a622c996..17473815 100644 --- a/src/components/ipc.cpp +++ b/src/components/ipc.cpp @@ -52,29 +52,22 @@ ipc::~ipc() { /** * Receive available ipc messages and delegate valid events */ -void ipc::receive_message() { +void ipc::receive_message(string buf) { m_log.info("Receiving ipc message"); - char buffer[BUFSIZ]{'\0'}; - ssize_t bytes_read{0}; + string payload{string_util::trim(std::move(buf), '\n')}; - if ((bytes_read = read(*m_fd, &buffer, BUFSIZ)) == -1) { - m_log.err("Failed to read from ipc channel (err: %s)", strerror(errno)); - } else if (bytes_read > 0) { - string payload{string_util::trim(string{buffer}, '\n')}; - - if (payload.find(ipc_command_prefix) == 0) { - m_sig.emit(signals::ipc::command{payload.substr(strlen(ipc_command_prefix))}); - } else if (payload.find(ipc_hook_prefix) == 0) { - m_sig.emit(signals::ipc::hook{payload.substr(strlen(ipc_hook_prefix))}); - } else if (payload.find(ipc_action_prefix) == 0) { - m_sig.emit(signals::ipc::action{payload.substr(strlen(ipc_action_prefix))}); - } else if (!payload.empty()) { - m_log.warn("Received unknown ipc message: (payload=%s)", payload); - } + if (payload.find(ipc_command_prefix) == 0) { + m_sig.emit(signals::ipc::command{payload.substr(strlen(ipc_command_prefix))}); + } else if (payload.find(ipc_hook_prefix) == 0) { + m_sig.emit(signals::ipc::hook{payload.substr(strlen(ipc_hook_prefix))}); + } else if (payload.find(ipc_action_prefix) == 0) { + m_sig.emit(signals::ipc::action{payload.substr(strlen(ipc_action_prefix))}); + } else if (!payload.empty()) { + m_log.warn("Received unknown ipc message: (payload=%s)", payload); } - m_fd = file_util::make_file_descriptor(m_path, O_RDONLY | O_NONBLOCK); + /* m_fd = file_util::make_file_descriptor(m_path, O_RDONLY | O_NONBLOCK); */ } /**