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.
This commit is contained in:
parent
b6661825ce
commit
47a2cce03d
@ -26,7 +26,7 @@ class inotify_watch {
|
||||
void remove(bool force = false);
|
||||
bool poll(int wait_ms = 1000) const;
|
||||
unique_ptr<inotify_event> get_event() const;
|
||||
bool await_match() const;
|
||||
unique_ptr<inotify_event> await_match() const;
|
||||
const string path() const;
|
||||
int get_file_descriptor() const;
|
||||
|
||||
|
@ -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<inotify_event> 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;
|
||||
|
@ -98,8 +98,9 @@ unique_ptr<inotify_event> 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_event> inotify_watch::await_match() const {
|
||||
auto event = get_event();
|
||||
return event->mask & m_mask ? std::move(event) : nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user