-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
FileSystemWatcher does not raise events when target directory is symlink (on linux) #25078
Comments
A kubernetes ConfigMap is using symlinked files and I'm thinking that this issue might be what's causing a reloadOnChange to not trigger when the ConfigMap is changed. |
If the file/folder being listened is a symlink, you have 100% chance to run into this bug, at least on Linux, very likely also OS X. I didn't test symlinks mechanism on Windows, since it's vastly different. |
We're running our dotnet core application on an alpine docker image so I'd say with high certainty that we run into the bug you describe above. By some magic chance you haven't figured out any workarounds? Long shot I know, but I had to ask =) |
Sorry for late response @stefanforsberg, I completely missed your message. I don't have a workaround other than using Possible, and the workaround with |
It seems like this is intentional: // Add a watch for the full path. If the path is already being watched, this will return
// the existing descriptor. This works even in the case of a rename. We also add the DONT_FOLLOW
// and EXCL_UNLINK flags to keep parity with Windows where we don't pickup symlinks or unlinked
// files (which don't exist in Windows)
int wd = Interop.Sys.INotifyAddWatch(_inotifyHandle, fullPath, (uint)(this._watchFilters | Interop.Sys.NotifyEvents.IN_DONT_FOLLOW | Interop.Sys.NotifyEvents.IN_EXCL_UNLINK)); however maybe the intention was for links within directory. If passed in explicitly we can perhaps check if given name is link and follow linked path instead. cc: @JeremyKuhne |
I started poking into this, and I'm wondering if we could add a new notify event to enable listening to the contents of symlinked directories: public enum NotifyFilters
{
FollowSymlinks
} And to avoid disrupting the world, the code @wfurt pasted above could add the // User did not pass the flag, so we keep adding the IN_DONT_FOLLOW flag as before
if ((filters & NotifyFilters.FollowSymlinks) == 0)
{
_watchFilters |= Interop.Sys.NotifyEvents.IN_DONT_FOLLOW;
}
int wd = Interop.Sys.INotifyAddWatch(_inotifyHandle, fullPath, (uint)(this._watchFilters | Interop.Sys.NotifyEvents.IN_EXCL_UNLINK)); Thoughts, @wfurt, @JeremyKuhne ? Edit: I suspect this won't work on Windows. I'll investigate more. |
I think there are two separate issues @carlossanlop. First one is if the directory we are asked to watch is symlink and then what do we do if there are symlinks within watched directory. For first one I think we can: For second I think it is more tricky. With following links the search may be huge if you ever have something like ../.. in the tree as well as there may be loop. You can try Directory.GetFiles("/sys/devices", "foo", SearchOption.AllDirectories)); There is really no way how the caller may know or have influence over. If we want to proceed, I would open new issue for API proposal. (2a) The current behavior seems to mimic old Windows behavior. However I do agree that on Unix symbolic links are generally handled transparently. My personal recommendation would be to try 1b (and perhaps mark it as breaking change) but I would be worried about recursively following symbolic links because of possible DoS and other pitfalls. |
Do you know if clearing IN_DONT_FOLLOW would still follow file symbolic links when watching a directory? The docs indicate that IN_DONT_FOLLOW controls following I don't think Windows has this type of functionality, so we might need to enumerate all paths to find the symlinks and add them. We'd have to watch multiple handles for each directory symlink. For file symlinks we'd have to watch the containing directory and make sure to only raise events for the single file. |
following nested links can be dangerous as that can create loops. (something windows do not need to deal with)
Something similar to #48151 |
I believe loops can be detected and short-circuited: would have to be if we followed them. Loops can exist on windows too. I agree it makes this more complicated. If all we do is follow the passed in link, why do that here? Why not instead just allow the user to do that with #24271. |
We could but #24271 sits there for very long time. And pushes the complexity to the caller. We could make small improvement to FileSystemWatcher instead without new API dependency. |
At least in the case I'm looking it I don't believe the root watch is a symlink directory. The symlinks are files in the directory. So following symlinks on the root directory won't help. See #36091 (comment). I'm not sure how many cases will really be helped by only following the root. IMHO a set of brand new API is easier since it is additive and well defined. I don't see any major blockers to #24271 (WinRT was mentioned but that's no longer a constraint), just some work to prototype more and drive it through API review. |
#36091 seems different. This issue was written for the linked root as far as I can tell. |
Steps to reproduce:
Launch a program similar to below:
Create empty file (or any other one):
touch /tmp/symdir/test.txt # Could be also /tmp/realdir/test.txt, since it's one and the same
No event being raised. Event is raised properly if we listen in
/tmp/realdir
instead.Since expected behaviour of linux programs is to handle symlinks transparently, I expected that
FileSystemWatcher
would properly raise events that happened in real directory. That didn't happen though (no events being raised, I also tested with other event types). I couldn't find similar issue so I consider it a bug, but if this is expected then it should probably be noted somewhere.Thank you in advance for looking into this.
The text was updated successfully, but these errors were encountered: