-
Notifications
You must be signed in to change notification settings - Fork 105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Created + Modified event is notified simultaneously #190
Comments
I's effective somewhat calling callbacks in order of WatcherFSEvents.cpp: void WatcherFSEvents::handleAddModDel( const Uint32& flags, const std::string& path,
std::string& dirPath, std::string& filePath ) {
if ( flags & efswFSEventStreamEventFlagItemRemoved ) {
// Since i don't know the order, at least i try to keep the data consistent with the real
// state
if ( !FileInfo::exists( path ) ) {
sendFileAction( ID, dirPath, filePath, Actions::Delete );
return;
}
}
if ( flags & efswFSEventStreamEventFlagItemModified ) {
sendFileAction( ID, dirPath, filePath, Actions::Modified );
return;
}
if ( flags & efswFSEventStreamEventFlagItemCreated ) {
if ( FileInfo::exists( path ) ) {
sendFileAction( ID, dirPath, filePath, Actions::Add );
return;
}
}
} If following events is notified, It will be broken:
|
Hi! Regarding your suggestion it will not work properly for some cases, for example, you could get a |
The following is reproducing code. #include <filesystem>
#include <fstream>
#include <iostream>
#include <barrier>
#include <format>
#include "efsw/efsw.h"
#include "efsw/WatcherFSEvents.hpp"
namespace fs = std::filesystem;
struct Context {
std::barrier<> sync{2};
efsw_action expect_state = EFSW_ADD;
};
static auto notify(efsw_watcher watcher, efsw_watchid watchid, const char *dir, const char *filename, efsw_action action, const char *old_filename, void *param) -> void {
auto ctx = reinterpret_cast<Context *>(param);
std::cout << std::format("called: {}", (int)action) << std::endl;
if (ctx->expect_state == action) {
ctx->sync.arrive();
}
}
auto main() -> int {
efsw_watcher watcher = efsw_create(false);
efsw_watcher_option opts[] = {
{ .option = EFSW_OPT_MAC_MODIFIED_FILTER, .value = efsw::efswFSEventStreamEventFlagItemModified },
};
struct Context ctx;
const efsw_watchid id = efsw_addwatch_withoptions(watcher, "./.build", notify, false, opts, 1, &ctx);
efsw_watch(watcher);
fs::path path("./.build/a.txt");
std::cout << "<<create stage>>" << std::endl;
std::ofstream ofs(path);
ctx.sync.arrive_and_wait();
std::cout << "<<edit stage>>" << std::endl;
ctx.expect_state = EFSW_MODIFIED;
ofs << "Hello World" << std::endl;
ofs.close();
ctx.sync.arrive_and_wait();
std::cout << "<<remove stage>>" << std::endl;
ctx.expect_state = EFSW_DELETE;
fs::remove(path);
ctx.sync.arrive_and_wait();
return 0;
} Result:
EDIT: I wrote debug message to void WatcherFSEvents::handleAddModDel( const Uint32& flags, const std::string& path,
std::string& dirPath, std::string& filePath ) {
bool created = flags & efswFSEventStreamEventFlagItemCreated;
bool edited = flags & ModifiedFlags;
bool removed = flags & efswFSEventStreamEventFlagItemRemoved;
std::cout << std::format("notify:action/created: {}, edited: {}, removed: {}", created, edited, removed) << std::endl;
.... Environment:
|
I've been investigating and it seems to be expected behaviour from FSEvent which sucks honestly. I've tried to work around the issue modifying FSStream parameters but it's not possible to avoid. So there's only one only possible partial solution: keep track of the Add events (which is the most problematic reported event). Given that this will effectively change the reported events behaviour on macOS events I added a new option to "sanitize" the reported events, the option is
Which is not perfect (IDK why still sends another modified) but it's good enough. The whole problem comes from how FSEvents is implemented to be fast and cheap and not exactly precise (this is why they coalesce the events). |
As the library package, it will be difficult to resolve this issue. |
It's fixable by just not using FSEvents, but that's just not the idea, this is good enough for basically any use case, since if you need more precision you can control it on the consumer side. I don't want to add more complexity to the current implementation, the idea is to have a general abstraction for each file system monitor OS API that there is, but not to build one on top of it. Although I must add that if you want it, you can actually use the Kqueue implementation for macOS, has its own limitations but it's more precise, in order to compile the macOS build to use Kqueue you must disable FSEvents by adding the compile flag |
I'm writing unit tests using
efsw
for my program.When I've operated from a file-create over a file-delete,
Created + Modified
event is notified simultaneously.Actually, following event is notified:
As a result, following callbacks is called:
Did you have same experiences?
This is also reported the other project.
howeyc/fsnotify#62
howeyc/fsnotify#54 (comment)
I've tried
latency
andkFSEventStreamCreateFlagNoDefer
but it is no effect.I've carried out a file operation manually but this situation is not occurred.
The text was updated successfully, but these errors were encountered: