It seems that the call will recurse indefinitely in a structure where a symlink loops back to parent directory. I suggest that a child FO whose canonical path is a prefix of its parent is excluded from the enumeration (= ignore upwards symlinks).
see e.g. report http://statistics.netbeans.org/exceptions/exception.do?id=610277, the binary scan seem to be stuck in home directory.
Created attachment 126323 [details]
Test to verify the system works
I've started with a test, and made it fail. Then I wanted to prevent that behavior, however I realized there is no check in masterfs API for symlinks. The bug 208392 does all the detection in parsing.api.
The only thing that comes to my mind is to move the code from parsing.api to masterfs. I leave it up to you guys whether you want to prepare such patch. If so, I happily use the symlink detection inside of FolderObj.getChildren(true).
Parsing API needs to donate the symlink detection code to openide.filesystems(?) for this request to be implementable.
Tomáši, let me know where the symlink detection code is, please.
Looking at the log http://statistics.netbeans.org/exceptions/exception.do?id=610277 there is no FO.getChildren(). Wrong link or did I overlooked it?
I will firstly look where the getChildren() is called and why.
From the attached log I cannot find the call of getChildren(true).
Also it's not so easy an API to correctly detect links (including Win NTFS junctions) should be added into FileUtil.
I've found several life locks caused by this issue in recent issues evaluations, back to P2.
Created attachment 136416 [details]
Patch with two possible implementations
I’ve checked the implementation in parsing API, and I copied the algorithm to FileUtil.isUnderRecursiveSymlink(FileObject).
I’ve also tried to implement a method that detects symlinks directly, FileUtil.isRecursiveSymlink(FileObject).
I guess the latter one is more user-friently, as the symbolic link can be detected even if the file path doesn’t contain two equal elements. The performance seems to be similar.
Can you please check the two methods and let me know if you find any problems in them (mainly performance), and which of them should be in the final patch for API review?
Thank you in advance.
- Tests are in module masterfs, because it’s easier to use
FileUtil.toFileObject(getWorkDir()) there. If you know about some better
place, please let me know.
- I only changed FileUtil.getChildren(boolean), I’m not sure whether
non-recursive methods should take care of recursive symlinks.
- Result of FileUtil.isUnderRecursiveSymlink depends on the path to link.
For example, let's have two symlinks in directory /a, named /a/b and /a/a,
both pointing to /a.
Method isUnderRecursiveSymlink() for the first one returns false, but for
the second one true. It's because it contains two elements with the same
name. Expected is false for both, because /a/a is not under a symlink.
Fixing only FileObject.getChildren(true), no API has been changed, FileUtil.isRecursiveSymlink is package private.
A more general API for accessing info about symbolic links should be introduced later.
Integrated into 'main-silver', will be available in build *201308212300* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress)
User: Jaroslav Havlin <email@example.com>
Log: #218795: FileObject.getChildren(true) should handle recursive symlinks gracefully