-
Notifications
You must be signed in to change notification settings - Fork 229
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
INotifyWatcher recursively adds watches but does not recursively remove #60
Comments
Nice catch. I haven't had a chance to work on rsnotify in a while, but one thing that may be important to keep in mind is that, to remove the watches, we probably shouldn't just recursively traverse the "root" and delete every watch for every entry we encounter. For example, we perhaps could have recursively traversed the root and for each directory found, check if it's in Also I'm not sure what would happen if one of the paths watched as a result of a recursive watch has since been removed from the file system. In that case it would not be found during the traversal and it would remain/leak/linger in the
Also from TLPI:
So I think monitoring for Currently the watches map is enum WatchKind {
Single(Watch),
Recursive(Vec<Watch>),
}
struct WatchEntry {
watch_kind: WatchKind,
mask: flags::Mask,
}
struct INotifyHandler {
...
watches: HashMap<PathBuf, WatchEntry>,
paths: Arc<RwLock<HashMap<Watch, PathBuf>>>
} As I understand it, Alternatively, we can perhaps just store the root of the recursive path, i.e. So to recap: differentiate between recursive and normal watches, and for recursive watches, store all of the watches that are associated with the given root, so for a given path you can access all of the watches added as a result of the recursive watch. The paths for these watches can easily be retrieved by cross-referencing with Or am I overthinking this? |
Another idea I've been toying with is returning a Continuing with your thoughts, you mention that
We could automatically watch that file (would inotify give a CREATE notification from the parent directory?) so that another call to The real problem I see with this approach is that if I watch |
Yeah I was considering something like that as well. IIRC one of the reasons we keep the paths is so that when we get an event, we can send the Path to the user so they know what path the event corresponds to. I guess we can offload this book-keeping to them (they'd get the watch descriptor and they'd need to maintain a map of wds to paths), but I think the objective of this package is to be a bit higher level than that.
Yep that's what I was getting at. I think it goes back to what you said:
I think right here we simply have to decide what behavior we prefer. Intuitively I agree that if the user specifically wants a recursive watch, it should continuously watch any new additions/changes, even though that's not what we're currently doing. I'm not sure if anyone would ever want the current behavior, where we recursively set up watches at the point-in-time at which the recursive watch was placed. If so I guess they could do it themselves manually by traversing the tree. Or perhaps they can control this with some sort of If we go that route, perhaps we can have a simple check where, if after a recursive watch on |
The (bad) reason for this, iirc, is that when I was creating this I was reading through other notify implementations in other languages, and some did just that, for simplicity perhaps. I think the logic went like: 1) glob Does this also concern other backends? I'd think it does. Generally, I think there backends should be a lot more low-level, and rsnotify should do a lot more itself than just selecting a backend and delegating everything to that. I outlined this in another thread, but revisiting for this:
Thoughts? |
I agree completely. I've also seen this be done in other implementations and I probably would've done the same thing. It's just that this issue made me question whether perhaps there's a better way. Then again, perhaps they do it this way for a good reason? Perhaps there are some problems down the line. That said, I think having behavior switches like
Yup. I labeled this one os-linux since this particular issue (unable to unwatch recursive watches) seems to affect the inotify back-end. I couldn't find any mention of recursive watches in the source files for the other back-ends. I agree with your ideas, perhaps they should go into its own separate tracking issue so everyone can join in on the discussion, since it's not specific to inotify as you say. That way we could also track progress towards that goal. I agree that perhaps we should slim down the amount of work the back-ends do. It seems like it's very possible for the implementations to diverge easily in quality and features, which is already very possible given the nature of this project in trying to normalize these very os-dependent features, and is perhaps further compounded when each back-end seems to need to recreate its own book-keeping etc. I'm not sure to what extent we can avoid that though. Perhaps we can learn something from std, for example how it handles Also I agree that it would be nice to have some optional debouncing functionality. I've seen other notification libraries in other languages include this. Currently it seems like everyone's forced to do it on their end. |
Here's where the INotifyHandler gets requests to add/remove watches.
Watches are definitely done recursively (that function does a
WalkDir
andadd_watch
for each entry). Remove watch only attempts to remove the given path.Just for completeness, here's the
add_watch_recursively
implementation.The text was updated successfully, but these errors were encountered: