Handle fs_event and poll errors in handle wrapper
This commit is contained in:
parent
db52106934
commit
895c1a6b51
@ -56,8 +56,8 @@ class controller : public signal_receiver<SIGN_PRIORITY_CONTROLLER, signals::eve
|
|||||||
|
|
||||||
void signal_handler(int signum);
|
void signal_handler(int signum);
|
||||||
|
|
||||||
void conn_cb(int status, int events);
|
void conn_cb(uv_poll_event events);
|
||||||
void confwatch_handler(const char* fname, int events, int status);
|
void confwatch_handler(const char* fname, uv_fs_event events);
|
||||||
void notifier_handler();
|
void notifier_handler();
|
||||||
void screenshot_handler();
|
void screenshot_handler();
|
||||||
|
|
||||||
|
@ -37,12 +37,16 @@ struct UVHandleGeneric {
|
|||||||
}
|
}
|
||||||
|
|
||||||
~UVHandleGeneric() {
|
~UVHandleGeneric() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
if (handle && !uv_is_closing((uv_handle_t*)handle)) {
|
if (handle && !uv_is_closing((uv_handle_t*)handle)) {
|
||||||
uv_close((uv_handle_t*)handle, close_callback);
|
uv_close((uv_handle_t*)handle, close_callback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void close() {
|
void cleanup_resources() {
|
||||||
if (handle) {
|
if (handle) {
|
||||||
delete handle;
|
delete handle;
|
||||||
handle = nullptr;
|
handle = nullptr;
|
||||||
@ -69,13 +73,21 @@ 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> {
|
||||||
PollHandle(uv_loop_t* loop, int fd, std::function<void(int, int)> fun);
|
PollHandle(uv_loop_t* loop, int fd, std::function<void(uv_poll_event)> fun, std::function<void(int)> err_cb);
|
||||||
void start(int events);
|
void start(int events);
|
||||||
|
void poll_cb(int status, int events);
|
||||||
|
|
||||||
|
std::function<void(uv_poll_event)> func;
|
||||||
|
std::function<void(int)> err_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FSEventHandle : public UVHandle<uv_fs_event_t, const char*, int, int> {
|
struct FSEventHandle : public UVHandle<uv_fs_event_t, const char*, int, int> {
|
||||||
FSEventHandle(uv_loop_t* loop, std::function<void(const char*, int, int)> fun);
|
FSEventHandle(uv_loop_t* loop, std::function<void(const char*, uv_fs_event)> fun, std::function<void(int)> err_cb);
|
||||||
void start(const string& path);
|
void start(const string& path);
|
||||||
|
void fs_event_cb(const char* path, int events, int status);
|
||||||
|
|
||||||
|
std::function<void(const char*, uv_fs_event)> func;
|
||||||
|
std::function<void(int)> err_cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PipeHandle : public UVHandleGeneric<uv_pipe_t, uv_stream_t, ssize_t, const uv_buf_t*> {
|
struct PipeHandle : public UVHandleGeneric<uv_pipe_t, uv_stream_t, ssize_t, const uv_buf_t*> {
|
||||||
@ -113,8 +125,9 @@ class eventloop {
|
|||||||
void run();
|
void run();
|
||||||
void stop();
|
void stop();
|
||||||
void signal_handler(int signum, std::function<void(int)> fun);
|
void signal_handler(int signum, std::function<void(int)> fun);
|
||||||
void poll_handler(int events, int fd, std::function<void(int, int)> fun);
|
void poll_handler(int events, int fd, std::function<void(uv_poll_event)> fun, std::function<void(int)> err_cb);
|
||||||
void fs_event_handler(const string& path, std::function<void(const char*, int, int)> fun);
|
void fs_event_handler(
|
||||||
|
const string& path, std::function<void(const char*, uv_fs_event)> fun, std::function<void(int)> err_cb);
|
||||||
void pipe_handle(int fd, std::function<void(const string)> fun, std::function<void(void)> eof_cb);
|
void pipe_handle(int fd, std::function<void(const string)> fun, std::function<void(void)> eof_cb);
|
||||||
void timer_handle(uint64_t timeout, uint64_t repeat, std::function<void(void)> fun);
|
void timer_handle(uint64_t timeout, uint64_t repeat, std::function<void(void)> fun);
|
||||||
AsyncHandle_t async_handle(std::function<void(void)> fun);
|
AsyncHandle_t async_handle(std::function<void(void)> fun);
|
||||||
|
@ -8,16 +8,8 @@
|
|||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
class file_descriptor;
|
|
||||||
class logger;
|
|
||||||
class signal_emitter;
|
class signal_emitter;
|
||||||
|
class logger;
|
||||||
/**
|
|
||||||
* Message types
|
|
||||||
*/
|
|
||||||
static constexpr const char* ipc_command_prefix{"cmd:"};
|
|
||||||
static constexpr const char* ipc_hook_prefix{"hook:"};
|
|
||||||
static constexpr const char* ipc_action_prefix{"action:"};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component used for inter-process communication.
|
* Component used for inter-process communication.
|
||||||
|
@ -130,7 +130,7 @@ void controller::trigger_action(string&& input_data) {
|
|||||||
std::unique_lock<std::mutex> guard(m_notification_mutex);
|
std::unique_lock<std::mutex> guard(m_notification_mutex);
|
||||||
|
|
||||||
if (m_notifications.inputdata.empty()) {
|
if (m_notifications.inputdata.empty()) {
|
||||||
m_notifications.inputdata = std::forward<string>(input_data);
|
m_notifications.inputdata = std::move(input_data);
|
||||||
trigger_notification();
|
trigger_notification();
|
||||||
} else {
|
} else {
|
||||||
m_log.trace("controller: Swallowing input event (pending data)");
|
m_log.trace("controller: Swallowing input event (pending data)");
|
||||||
@ -163,13 +163,7 @@ void controller::stop(bool reload) {
|
|||||||
eloop->stop();
|
eloop->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void controller::conn_cb(int status, int) {
|
void controller::conn_cb(uv_poll_event) {
|
||||||
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();
|
int xcb_error = m_connection.connection_has_error();
|
||||||
if ((xcb_error = m_connection.connection_has_error()) > 0) {
|
if ((xcb_error = m_connection.connection_has_error()) > 0) {
|
||||||
m_log.err("X connection error, terminating... (what: %s)", m_connection.error_str(xcb_error));
|
m_log.err("X connection error, terminating... (what: %s)", m_connection.error_str(xcb_error));
|
||||||
@ -200,7 +194,7 @@ void controller::signal_handler(int signum) {
|
|||||||
stop(signum == SIGUSR1);
|
stop(signum == SIGUSR1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void controller::confwatch_handler(const char* filename, int, int) {
|
void controller::confwatch_handler(const char* filename, uv_fs_event) {
|
||||||
m_log.notice("Watched config file changed %s", filename);
|
m_log.notice("Watched config file changed %s", filename);
|
||||||
stop(true);
|
stop(true);
|
||||||
}
|
}
|
||||||
@ -247,15 +241,19 @@ void controller::read_events(bool confwatch) {
|
|||||||
eloop = std::make_unique<eventloop>();
|
eloop = std::make_unique<eventloop>();
|
||||||
|
|
||||||
eloop->poll_handler(
|
eloop->poll_handler(
|
||||||
UV_READABLE, m_connection.get_file_descriptor(), [this](int status, int events) { conn_cb(status, events); });
|
UV_READABLE, m_connection.get_file_descriptor(), [this](uv_poll_event events) { conn_cb(events); },
|
||||||
|
[](int status) { throw runtime_error("libuv error while polling X connection: "s + uv_strerror(status)); });
|
||||||
|
|
||||||
for (auto s : {SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGALRM}) {
|
for (auto s : {SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGALRM}) {
|
||||||
eloop->signal_handler(s, [this](int signum) { signal_handler(signum); });
|
eloop->signal_handler(s, [this](int signum) { signal_handler(signum); });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (confwatch) {
|
if (confwatch) {
|
||||||
eloop->fs_event_handler(m_conf.filepath(),
|
eloop->fs_event_handler(
|
||||||
[this](const char* path, int events, int status) { confwatch_handler(path, events, status); });
|
m_conf.filepath(), [this](const char* path, uv_fs_event events) { confwatch_handler(path, events); },
|
||||||
|
[this](int status) {
|
||||||
|
m_log.err("libuv error while watching config file for changes: %s", uv_strerror(status));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_ipc) {
|
if (m_ipc) {
|
||||||
|
@ -13,22 +13,22 @@ POLYBAR_NS
|
|||||||
void close_callback(uv_handle_t* handle) {
|
void close_callback(uv_handle_t* handle) {
|
||||||
switch (handle->type) {
|
switch (handle->type) {
|
||||||
case UV_ASYNC:
|
case UV_ASYNC:
|
||||||
static_cast<AsyncHandle*>(handle->data)->close();
|
static_cast<AsyncHandle*>(handle->data)->cleanup_resources();
|
||||||
break;
|
break;
|
||||||
case UV_FS_EVENT:
|
case UV_FS_EVENT:
|
||||||
static_cast<FSEventHandle*>(handle->data)->close();
|
static_cast<FSEventHandle*>(handle->data)->cleanup_resources();
|
||||||
break;
|
break;
|
||||||
case UV_POLL:
|
case UV_POLL:
|
||||||
static_cast<PollHandle*>(handle->data)->close();
|
static_cast<PollHandle*>(handle->data)->cleanup_resources();
|
||||||
break;
|
break;
|
||||||
case UV_TIMER:
|
case UV_TIMER:
|
||||||
static_cast<TimerHandle*>(handle->data)->close();
|
static_cast<TimerHandle*>(handle->data)->cleanup_resources();
|
||||||
break;
|
break;
|
||||||
case UV_SIGNAL:
|
case UV_SIGNAL:
|
||||||
static_cast<SignalHandle*>(handle->data)->close();
|
static_cast<SignalHandle*>(handle->data)->cleanup_resources();
|
||||||
break;
|
break;
|
||||||
case UV_NAMED_PIPE:
|
case UV_NAMED_PIPE:
|
||||||
static_cast<PipeHandle*>(handle->data)->close();
|
static_cast<PipeHandle*>(handle->data)->cleanup_resources();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
@ -51,25 +51,48 @@ void SignalHandle::start(int signum) {
|
|||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
// PollHandle {{{
|
// PollHandle {{{
|
||||||
// TODO wrap callback and handle status
|
PollHandle::PollHandle(uv_loop_t* loop, int fd, std::function<void(uv_poll_event)> fun, std::function<void(int)> err_cb)
|
||||||
PollHandle::PollHandle(uv_loop_t* loop, int fd, std::function<void(int, int)> fun) : UVHandle(fun) {
|
: UVHandle([this](int status, int events) { poll_cb(status, events); }), func(fun), err_cb(err_cb) {
|
||||||
UV(uv_poll_init, loop, handle, fd);
|
UV(uv_poll_init, loop, handle, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PollHandle::start(int events) {
|
void PollHandle::start(int events) {
|
||||||
UV(uv_poll_start, handle, events, callback);
|
UV(uv_poll_start, handle, events, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PollHandle::poll_cb(int status, int events) {
|
||||||
|
if (status < 0) {
|
||||||
|
close();
|
||||||
|
err_cb(status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
func((uv_poll_event)events);
|
||||||
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
// FSEventHandle {{{
|
// FSEventHandle {{{
|
||||||
// TODO wrap callback and handle status
|
FSEventHandle::FSEventHandle(
|
||||||
FSEventHandle::FSEventHandle(uv_loop_t* loop, std::function<void(const char*, int, int)> fun) : UVHandle(fun) {
|
uv_loop_t* loop, std::function<void(const char*, uv_fs_event)> fun, std::function<void(int)> err_cb)
|
||||||
|
: UVHandle([this](const char* path, int events, int status) { fs_event_cb(path, events, status); })
|
||||||
|
, func(fun)
|
||||||
|
, err_cb(err_cb) {
|
||||||
UV(uv_fs_event_init, loop, handle);
|
UV(uv_fs_event_init, loop, handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FSEventHandle::start(const string& path) {
|
void FSEventHandle::start(const string& path) {
|
||||||
UV(uv_fs_event_start, handle, callback, path.c_str(), 0);
|
UV(uv_fs_event_start, handle, callback, path.c_str(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FSEventHandle::fs_event_cb(const char* path, int events, int status) {
|
||||||
|
if (status < 0) {
|
||||||
|
close();
|
||||||
|
err_cb(status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
func(path, (uv_fs_event)events);
|
||||||
|
}
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
// PipeHandle {{{
|
// PipeHandle {{{
|
||||||
@ -182,13 +205,15 @@ void eventloop::signal_handler(int signum, std::function<void(int)> fun) {
|
|||||||
m_sig_handles.back()->start(signum);
|
m_sig_handles.back()->start(signum);
|
||||||
}
|
}
|
||||||
|
|
||||||
void eventloop::poll_handler(int events, int fd, std::function<void(int, int)> fun) {
|
void eventloop::poll_handler(
|
||||||
m_poll_handles.emplace_back(std::make_unique<PollHandle>(get(), fd, fun));
|
int events, int fd, std::function<void(uv_poll_event)> fun, std::function<void(int)> err_cb) {
|
||||||
|
m_poll_handles.emplace_back(std::make_unique<PollHandle>(get(), fd, fun, err_cb));
|
||||||
m_poll_handles.back()->start(events);
|
m_poll_handles.back()->start(events);
|
||||||
}
|
}
|
||||||
|
|
||||||
void eventloop::fs_event_handler(const string& path, std::function<void(const char*, int, int)> fun) {
|
void eventloop::fs_event_handler(
|
||||||
m_fs_event_handles.emplace_back(std::make_unique<FSEventHandle>(get(), fun));
|
const string& path, std::function<void(const char*, uv_fs_event)> fun, std::function<void(int)> err_cb) {
|
||||||
|
m_fs_event_handles.emplace_back(std::make_unique<FSEventHandle>(get(), fun, err_cb));
|
||||||
m_fs_event_handles.back()->start(path);
|
m_fs_event_handles.back()->start(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,13 @@
|
|||||||
|
|
||||||
POLYBAR_NS
|
POLYBAR_NS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Message types
|
||||||
|
*/
|
||||||
|
static constexpr const char* ipc_command_prefix{"cmd:"};
|
||||||
|
static constexpr const char* ipc_hook_prefix{"hook:"};
|
||||||
|
static constexpr const char* ipc_action_prefix{"action:"};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create instance
|
* Create instance
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user