From 47a2cce03de7c2bf2322d515504ef1bb9cd37ad0 Mon Sep 17 00:00:00 2001 From: Chase Geigle Date: Tue, 24 Jan 2017 00:10:55 -0600 Subject: [PATCH] fix: Ensure reloading when IN_IGNORED fired on config (#371) This fixes a "bug" where polybar wouldn't reload on a configuration file change on some configurations of vim, which don't actually issue any IN_MODIFY events because they choose to move the file, replace it with a new one, and then delete the file instead. To work around this, we now also listen for IN_IGNORED which fires when the file we are watching is destroyed. When this happens, we re-attach the configuration file watcher to the new file and reload. --- include/utils/inotify.hpp | 2 +- src/components/controller.cpp | 19 +++++++++++++++++-- src/utils/inotify.cpp | 5 +++-- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/include/utils/inotify.hpp b/include/utils/inotify.hpp index 9a964eb7..207d7b02 100644 --- a/include/utils/inotify.hpp +++ b/include/utils/inotify.hpp @@ -26,7 +26,7 @@ class inotify_watch { void remove(bool force = false); bool poll(int wait_ms = 1000) const; unique_ptr get_event() const; - bool await_match() const; + unique_ptr await_match() const; const string path() const; int get_file_descriptor() const; diff --git a/src/components/controller.cpp b/src/components/controller.cpp index 125b7723..08907273 100644 --- a/src/components/controller.cpp +++ b/src/components/controller.cpp @@ -246,7 +246,7 @@ void controller::read_events() { if (m_confwatch) { m_log.trace("controller: Attach config watch"); - m_confwatch->attach(IN_MODIFY); + m_confwatch->attach(IN_MODIFY | IN_IGNORED); fds.emplace_back((fd_confwatch = m_confwatch->get_file_descriptor())); } @@ -281,7 +281,22 @@ void controller::read_events() { } // Process event on the config inotify watch fd - if (fd_confwatch > -1 && FD_ISSET(fd_confwatch, &readfds) && m_confwatch->await_match()) { + unique_ptr confevent; + if (fd_confwatch > -1 && FD_ISSET(fd_confwatch, &readfds) && (confevent = m_confwatch->await_match())) { + if (confevent->mask & IN_IGNORED) { + // IN_IGNORED: file was deleted or filesystem was unmounted + // + // This happens in some configurations of vim when a file is saved, + // since it is not actually issuing calls to write() but rather + // moves a file into the original's place after moving the original + // file to a different location (and subsequently deleting it). + // + // We need to re-attach the watch to the new file in this case. + fds.erase(std::remove_if(fds.begin(), fds.end(), [fd_confwatch](int fd) { return fd == fd_confwatch; }), fds.end()); + m_confwatch = inotify_util::make_watch(m_confwatch->path()); + m_confwatch->attach(IN_MODIFY | IN_IGNORED); + fds.emplace_back((fd_confwatch = m_confwatch->get_file_descriptor())); + } m_log.info("Configuration file changed"); g_terminate = 1; g_reload = 1; diff --git a/src/utils/inotify.cpp b/src/utils/inotify.cpp index 5ece28fb..e5f1bed6 100644 --- a/src/utils/inotify.cpp +++ b/src/utils/inotify.cpp @@ -98,8 +98,9 @@ unique_ptr inotify_watch::get_event() const { /** * Wait for matching event */ -bool inotify_watch::await_match() const { - return (get_event()->mask & m_mask) == m_mask; +unique_ptr inotify_watch::await_match() const { + auto event = get_event(); + return event->mask & m_mask ? std::move(event) : nullptr; } /**