Skip to content
This repository was archived by the owner on Apr 14, 2022. It is now read-only.
This repository was archived by the owner on Apr 14, 2022. It is now read-only.

symlink loops recursively followed #2006

Open
@joelhock

Description

@joelhock
  • 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions