zobo / php-language-server

PHP Implementation of the VS Code Language Server Protocol 🆚↔🖥

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Since version 1.0.12 the language server runs out of memory

eedelbroek opened this issue · comments

Since version 1.0.12 the language server runs out of memory. So maybe this is caused by an internal loop.
I already increased the memory limit to 6095M, but the same result.

Command:
DEBUG Running '/usr/local/Cellar/php@7.4/7.4.20/bin/php' '-n' '-c' '/private/var/folders/__/mpdnyh613959vmhfbl19gl700000gq/T/eO0DcQ' '/Users/eddy/.vscode/extensions/zobo.php-intellisense-1.0.12/vendor/felixfbecker/language-server/bin/php-language-server.php' '--tcp=127.0.0.1:51312' '--memory-limit=6095M'

After parsing 20 files:
PHP Fatal error: Allowed memory size of 6391070720 bytes exhausted (tried to allocate 262144 bytes) in /Users/eddy/.vscode/extensions/zobo.php-intellisense-1.0.12/vendor/felixfbecker/language-server/src/DefinitionResolver.php on line 910

Hi! Thanks for the report. This could be it yes. Can you look at the output while it is indexing and try to "guess" what file it happens in. Do you think you have a class or set of classes, interfaces, traits that could form an endless loop?
I can probably add some code to prevent this.

You can enable additional logging in settings
image

setting php-intellisense.trace.server

Thanks!

I'll probably need a stack trace. Ideally you'd enable xdebug in your php installation and change a line of code in the source:
php-language-server.php, line 43 $xdebugHandler->check(); and comment that out. Source is in /Users/eddy/.vscode/extensions/zobo.php-intellisense-1.0.12/vendor/felixfbecker/language-serve/bin/php-language-server.php

I'll probably add a setting to allow switching this on or off.

If you can do that, you should get a back trace when the problem happens.

Also, the last Parsing .... line should indicate which file triggered the error.
If you can, consider sharing it with me, or if you can, try to isolate in what part of the file the error happens.

Thanks.

I found the loop and made a quick fix by checking the length of the debug_backtrace result (see below) But it is better to keep track of the depth by adding another parameter to the resolveExpressionNodeToType method. See also the debug_backtrace in JSON format.

DefinitionResolver.php

    /**
     * Given an expression node, resolves that expression recursively to a type.
     * If the type could not be resolved, returns Types\Mixed_.
     *
     * @param Node\Expression $expr
     * @return \phpDocumentor\Reflection\Type|null
     */
    public function resolveExpressionNodeToType($expr)
    {
        if(count(debug_backtrace()) > 1000) {
            throw new \Exception("Endless recursive loop detected");
        }
        
        // PARENTHESIZED EXPRESSION
        // Retrieve inner expression from parenthesized expression
        while ($expr instanceof Node\Expression\ParenthesizedExpression) {

39 - debug_backtrace.json.zip

Thanks so much for the dump. I think I can get what I need from it. I think I already know where the problem came from I just need to find the right way to implement what I need. Will get back as soon as I can,

Thanks again for providing this backtrace. I figured the issue was this sort of code:

function aaa($var) {
  $var = $var;

In the last release I added some code (that I committed quite some time ago) that allowed hovering over an assignment expression $a = ... to resolve to the proper type.

I did not have a test case like this and the resolver got stuck in the loop:

  1. What is the type of $var =?
  2. Oh, its the same as = $var, lets find it.
  3. Ok, found $var =, what type is it?
  4. It's = $var. What type is it?
  5. Ok, found $var =, what type is it?
    ...

Have made changes that more explicitly check if the current node is to be resolved into the current expression.

Fixed in #41

Thanks for the fix. Version 1.0.13 works fine now