Skip to content

rg cannot traverse arbitrarily deep directories like GNU grep. #3259

@collinfunk

Description

@collinfunk

Here is how you can reproduce:

$ rg --version | head -n 1
ripgrep 15.1.0 (rev 0a88cccd51)
$ grep --version | head -n 1
grep (GNU grep) 3.12.14-071a
$ mkdir -p `yes a/ | head -n $((32 * 1024)) | tr -d '\n'`
$ while cd $(yes a/ | head -n 1024 | tr -d '\n'); do :; done 2>/dev/null
$ pwd | tr '/' '\n' | wc -l
32771
$ echo hello | tee $(seq 100) > /dev/null
$ (cd $HOME && grep -r '^hello$' a | wc -l)
100
$ (cd $HOME && rg '^hello$' a)
rg: [trimmed long file name]: File name too long (os error 36)

It also seems that rg unnecessarily computes the current working
directory for each file processed. That becomes inefficient when
ENAMETOOLONG is returned and the openat (dirfd, "..", ...) to root
fallback has to be used. This can be seen below from the same directory:

$ pwd | tr '/' '\n' | wc -l
32771
$ time grep -r '^hello$' | wc -l
100

real	0m0.004s
user	0m0.001s
sys	0m0.005s
$ time rg --no-heading --line-number '^hello$' | wc -l

thread '<unknown>' (1405793) has overflowed its stack
fatal runtime error: stack overflow, aborting
100

real	2m59.479s
user	0m22.209s
sys	19m10.741s

I am not sure where the stack overflow is from. Probably a large item on
the stack, instead of deep recursion?

Also, during that test you can see that lots of memory is allocated
seemingly only for the file names:

$ (ulimit -v $(($(numfmt --from=iec 9G) / 1024)) && rg --no-heading --line-number '^hello$')
memory allocation of 63663 bytes failed
Aborted                    (core dumped) ( ulimit -v $(($(numfmt --from=iec 9G) / 1024)) && rg --no-heading --line-number '^hello$' )

Note that creating a directory this deep might depend on your file
system, and shells other than bash or zsh will almost certainly fail
to cd this deep.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions