diff --git a/include/components/controller.hpp b/include/components/controller.hpp index 99f25942..023ebad0 100644 --- a/include/components/controller.hpp +++ b/include/components/controller.hpp @@ -53,6 +53,8 @@ class controller bool enqueue(event&& evt); bool enqueue(string&& input_data); + void signal_handler(int signum); + void conn_cb(int status, int events); void ipc_cb(string buf); @@ -88,7 +90,7 @@ class controller unique_ptr m_ipc; unique_ptr m_confwatch; - eventloop eloop; + std::unique_ptr eloop; /** * \brief State flag diff --git a/include/components/eventloop.hpp b/include/components/eventloop.hpp index bffe88e1..dcdd9517 100644 --- a/include/components/eventloop.hpp +++ b/include/components/eventloop.hpp @@ -6,6 +6,30 @@ POLYBAR_NS +template +struct cb_helper { + std::function func; + + static void callback(H* context, Args... args) { + const auto unpackedThis = static_cast(context->data); + return unpackedThis->func(std::forward(args)...); + } +}; + +struct SignalHandle { + SignalHandle(uv_loop_t* loop, std::function fun) { + handle = std::make_unique(); + // TODO handle return value + uv_signal_init(loop, handle.get()); + cb = cb_helper{fun}; + + handle->data = &cb; + }; + + std::unique_ptr handle; + cb_helper cb; +}; + class eventloop { public: eventloop(); @@ -16,14 +40,28 @@ class eventloop { void stop(); /** - * TODO remove + * TODO make protected */ uv_loop_t* get() const { return m_loop.get(); } + void signal_handler(int signum, std::function fun) { + auto handle = std::make_unique(get(), fun); + uv_signal_start(handle->handle.get(), &handle->cb.callback, signum); + m_sig_handles.push_back(std::move(handle)); + } + + protected: + template + static void generic_cb(H* handle, Args&&... args) { + (static_cast(handle->data).*F)(std::forward(args)...); + } + private: std::unique_ptr m_loop{nullptr}; + + vector> m_sig_handles; }; POLYBAR_NS_END diff --git a/include/utils/file.hpp b/include/utils/file.hpp index 0e062936..ebbf1921 100644 --- a/include/utils/file.hpp +++ b/include/utils/file.hpp @@ -29,7 +29,7 @@ class file_ptr { class file_descriptor { public: - explicit file_descriptor(const string& path, int flags = 0); + explicit file_descriptor(const string& path, int flags = 0, bool autoclose = true); explicit file_descriptor(int fd, bool autoclose = true); ~file_descriptor(); diff --git a/src/components/controller.cpp b/src/components/controller.cpp index 21c8ee88..8cbf9073 100644 --- a/src/components/controller.cpp +++ b/src/components/controller.cpp @@ -134,7 +134,6 @@ bool controller::run(bool writeback, string snapshot_dst) { read_events(); if (m_event_thread.joinable()) { - enqueue(make_quit_evt(static_cast(g_reload))); m_event_thread.join(); } @@ -179,7 +178,7 @@ void controller::conn_cb(int, int) { if (m_connection.connection_has_error()) { g_terminate = 1; g_reload = 0; - eloop.stop(); + eloop->stop(); return; } @@ -204,10 +203,10 @@ static void conn_cb_wrapper(uv_poll_t* handle, int status, int events) { static_cast(handle->data)->conn_cb(status, events); } -static void signal_cb_wrapper(uv_signal_t* handle, int signum) { +void controller::signal_handler(int signum) { g_terminate = 1; g_reload = (signum == SIGUSR1); - static_cast(handle->loop->data)->stop(); + eloop->stop(); } static void confwatch_cb_wrapper(uv_fs_event_t* handle, const char* fname, int, int) { @@ -249,7 +248,8 @@ static void ipc_read_cb_wrapper(uv_stream_t* stream, ssize_t nread, const uv_buf void controller::read_events() { m_log.info("Entering event loop (thread-id=%lu)", this_thread::get_id()); - auto loop = eloop.get(); + eloop = std::make_unique(); + auto loop = eloop->get(); auto conn_handle = std::make_unique(); uv_poll_init(loop, conn_handle.get(), m_connection.get_file_descriptor()); @@ -257,15 +257,8 @@ void controller::read_events() { uv_poll_start(conn_handle.get(), UV_READABLE, conn_cb_wrapper); - std::vector> handles; - for (auto s : {SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGALRM}) { - auto signal_handle = std::make_unique(); - uv_signal_init(loop, signal_handle.get()); - signal_handle->data = this; - - uv_signal_start(signal_handle.get(), signal_cb_wrapper, s); - handles.push_back(std::move(signal_handle)); + eloop->signal_handler(s, [this](int signum) { signal_handler(signum); }); } auto conf_handle = std::unique_ptr(nullptr); @@ -288,7 +281,8 @@ void controller::read_events() { uv_read_start((uv_stream_t*)ipc_handle.get(), ipc_alloc_cb, ipc_read_cb_wrapper); } - eloop.run(); + eloop->run(); + eloop.reset(); } /** diff --git a/src/components/eventloop.cpp b/src/components/eventloop.cpp index 99e2e35e..d3d4a1bc 100644 --- a/src/components/eventloop.cpp +++ b/src/components/eventloop.cpp @@ -10,10 +10,30 @@ eventloop::eventloop() { m_loop->data = this; } +static void close_walk_cb(uv_handle_t* handle, void*) { + if (!uv_is_closing(handle)) { + uv_close(handle, nullptr); + } +} + +/** + * Completely closes everything in the loop. + * + * After this function returns, uv_loop_close can be called. + */ +static void close_loop(uv_loop_t* loop) { + uv_walk(loop, close_walk_cb, nullptr); + uv_run(loop, UV_RUN_DEFAULT); + // TODO handle return value +} + eventloop::~eventloop() { if (m_loop) { + close_loop(m_loop.get()); uv_loop_close(m_loop.get()); // TODO handle return value + + m_loop.reset(); } } diff --git a/src/components/ipc.cpp b/src/components/ipc.cpp index 17473815..7487a910 100644 --- a/src/components/ipc.cpp +++ b/src/components/ipc.cpp @@ -34,15 +34,13 @@ ipc::ipc(signal_emitter& emitter, const logger& logger) : m_sig(emitter), m_log( } m_log.info("Created ipc channel at: %s", m_path); - 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, false); } /** * Deconstruct ipc handler */ ipc::~ipc() { - m_fd.reset(); - if (!m_path.empty()) { m_log.trace("ipc: Removing file handle"); unlink(m_path.c_str()); @@ -66,8 +64,6 @@ void ipc::receive_message(string buf) { } 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); */ } /** diff --git a/src/modules/xwindow.cpp b/src/modules/xwindow.cpp index 010750c1..a6eccef5 100644 --- a/src/modules/xwindow.cpp +++ b/src/modules/xwindow.cpp @@ -86,6 +86,7 @@ namespace modules { * Handler for XCB_PROPERTY_NOTIFY events */ void xwindow_module::handle(const evt::property_notify& evt) { + m_log.notice("%s: handle Thread id: %i", name(), concurrency_util::thread_id(this_thread::get_id())); if (evt->atom == _NET_ACTIVE_WINDOW) { update(true); } else if (evt->atom == _NET_CURRENT_DESKTOP) { diff --git a/src/utils/file.cpp b/src/utils/file.cpp index 83f51ddb..d8303054 100644 --- a/src/utils/file.cpp +++ b/src/utils/file.cpp @@ -52,7 +52,7 @@ file_ptr::operator int() const { // }}} // implementation of file_descriptor {{{ -file_descriptor::file_descriptor(const string& path, int flags) { +file_descriptor::file_descriptor(const string& path, int flags, bool autoclose) : m_autoclose(autoclose) { if ((m_fd = open(path.c_str(), flags)) == -1) { throw system_error("Failed to open file descriptor"); }