symlink loops recursively followed #2006
Description
- Language Server version: 0.5.45.0
- OS and version: linux
- Python version (& distribution if applicable, e.g. Anaconda): various 2.7-3.X
Expected behaviour
recursive symbolic loops to not be followed until stat() fails with ELOOP (Too many levels of symbolic links)
Actual behaviour
given this workspace:
$ ls -Rl
.:
total 8.0K
drwxr-xr-x 2 joel atl 4.0K 20200424 22:39:58 bar/
drwxr-xr-x 2 joel atl 4.0K 20200424 22:38:37 foo/
-rw-r--r-- 1 joel atl 0 20200424 20:21:41 test.py
./bar:
total 0
lrwxrwxrwx 1 joel atl 6 20200424 22:37:47 foo -> ../foo/
-rw-r--r-- 1 joel atl 0 20200424 22:39:58 other.notpy
-rw-r--r-- 1 joel atl 0 20200424 22:39:54 other.py
./foo:
total 0
lrwxrwxrwx 1 joel atl 6 20200424 22:37:52 bar -> ../bar/
-rw-r--r-- 1 joel atl 0 20200424 22:38:37 it.notpy
-rw-r--r-- 1 joel atl 0 20200424 22:38:32 it.py
strace of the LSP has lots of recursive transversals, ending with:
14028 lstat("/usr/scratch/joel/testsymlink/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/
foo/bar/foo/bar/foo/bar/foo/bar/other.py", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0
14028 geteuid() = 1012
14028 stat("/usr/scratch/joel/testsymlink/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo", 0x7fd98fffcb00) = -1 ELOOP (Too many levels of symbolic links)
Logs
in this trivial example, it completes fine since ELOOP failure is quickly reached. in our more complex setup with recursive symbolic links on NFS, it causes startup to take forever.
Notes
This is likely similar to the closed #181 , which people have recently started commenting on again.
Also, (this observation might warrant a separate issue) this recursive loop in our actual workspace is avoided in vscode itself via enumerating the recursive symlinks in files.watcherExclude
, which stops decent once a /**
is matched, but it seems the python LSP does a full recursive decent of the entire source tree, even though files found during the descent might eventually be discarded via the exclude.