Skip to content

Commit

Permalink
conf: fix reloading on IN_CREATE
Browse files Browse the repository at this point in the history
If the config file is a symlink, wayfire attempts to watch the parent
directory so that, if replaced via a subsequent `ln -sf`, it'll still
be notified. When notified, however, wayfire doesn't immediately
reload the config file. Rather, as this event may be triggered by any
file creation in the directory, we first make sure that the config file
really is the one being created anew.

Unfortunately, ln -sf is special: It'll create a randomly named file in
the directory before renameat(2)ing it to the proper location. So it
does generate an IN_CREATE event, but to know that the file was changed,
we need to additionally monitor for IN_MOVED_TO.

Fixes #2210.
  • Loading branch information
atalii committed Mar 18, 2024
1 parent 3aa8c3f commit 5a94379
Showing 1 changed file with 18 additions and 11 deletions.
29 changes: 18 additions & 11 deletions src/default-config-backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <wayfire/plugin.hpp>
#include <wayfire/core.hpp>

#include <cstring>
#include <sys/inotify.h>
#include <filesystem>
#include <unistd.h>
Expand All @@ -20,7 +21,7 @@ static int wd_cfg_dir, wd_cfg_file;

static void add_watch(int fd)
{
wd_cfg_dir = inotify_add_watch(fd, config_dir.c_str(), IN_CREATE);
wd_cfg_dir = inotify_add_watch(fd, config_dir.c_str(), IN_CREATE | IN_MOVED_TO);
wd_cfg_file = inotify_add_watch(fd, config_file.c_str(), IN_CLOSE_WRITE);
}

Expand Down Expand Up @@ -58,18 +59,24 @@ static int handle_config_updated(int fd, uint32_t mask, void *data)
ptr += sizeof(inotify_event) + event->len)
{
event = reinterpret_cast<inotify_event*>(ptr);
// We reload in two main cases:
// We reload in two cases:
//
// - Config file itself was modified
// - Config file was created inside parent directory
should_reload |=
(event->wd == wd_cfg_file) || (cfg_file_basename == event->name);

if ((event->name == cfg_file_basename) && (event->wd == wd_cfg_dir))
// 1. The config file itself was modified, or...
should_reload |= event->wd == wd_cfg_file;
// 2. The config file was moved nto or created inside the parent directory.
if (event->len > 0)
{
inotify_rm_watch(fd, wd_cfg_file);
wd_cfg_file =
inotify_add_watch(fd, (config_dir + "/" + cfg_file_basename).c_str(), IN_CLOSE_WRITE);
// This is UB unless event->len > 0.
auto name_matches = cfg_file_basename == event->name;

if (name_matches)
{
inotify_rm_watch(fd, wd_cfg_file);
wd_cfg_file =
inotify_add_watch(fd, (config_dir + "/" + cfg_file_basename).c_str(), IN_CLOSE_WRITE);
}

should_reload |= name_matches;
}
}

Expand Down

0 comments on commit 5a94379

Please sign in to comment.