Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version 5.7 fails with exit code 139 #9340

Closed
tarlepp opened this issue Feb 19, 2023 · 22 comments
Closed

Version 5.7 fails with exit code 139 #9340

tarlepp opened this issue Feb 19, 2023 · 22 comments

Comments

@tarlepp
Copy link
Contributor

tarlepp commented Feb 19, 2023

With version 5.6 I get this:

dev@php-fpm /app (chore(deps)/dependency-update)> ./vendor/bin/psalm --version
Psalm 5.6.0@e784128902dfe01d489c4123d69918a9f3c1eac5
dev@php-fpm /app (chore(deps)/dependency-update)> ./vendor/bin/psalm src/Controller/IndexController.php
Target PHP version: 8.2 (inferred from current PHP version) Enabled extensions: pdo.
Scanning files...
Deprecation: Psalm stubs for ext-apcu loaded using legacy way. Instead, please declare ext-apcu as dependency in composer.json or use <enableExtensions> and/or <disableExtensions> directives in Psalm config.
Analyzing files...

░

To whom it may concern: Psalm cannot detect unused classes, methods and properties
when analyzing individual files and folders. Run on the full project to enable
complete unused code detection.
------------------------------
                              
       No errors found!       
                              
------------------------------

Checks took 1.59 seconds and used 316.663MB of memory
Psalm was able to infer types for 100% of the codebase
dev@php-fpm /app (chore(deps)/dependency-update)>

And with version 5.7 I get this:

dev@php-fpm /app (chore(deps)/dependency-update)> ./vendor/bin/psalm --version
Psalm 5.7.0@d934875532c7eb344d6b2914c3525f116a6b0cf2
dev@php-fpm /app (chore(deps)/dependency-update)> ./vendor/bin/psalm src/Controller/IndexController.php
dev@php-fpm /app (chore(deps)/dependency-update) [139]> 

And in the version 5.7 the exit code is 139, so there is something fishy going on.

Also tried to run with --threads=1 option and the end results is the same.

@weirdan
Copy link
Collaborator

weirdan commented Feb 19, 2023

To anyone who also has this issue

Please react with heart (:heart:) to the issue itself, so that we can gauge the impact.


And in the version 5.7 the exit code is 139, so there is something fishy going on.

This exit code usually indicates a segmentation fault, meaning the problem is in PHP (or one of its extensions), and Psalm just triggers it somehow. Compiling PHP with debug symbols (or installing them with your package manager), getting the core dump and analyzing it with gdb may help to see what PHP was doing when the crash happened. See https://bugs.php.net/bugs-generating-backtrace.php

Alternatively, you may try to disable all non-essential extensions. The extensions Psalm requires are listed here:

// the following list was taken from vendor/composer/platform_check.php
// It includes both Psalm's requirements (from composer.json) and the
// requirements of our dependencies `netresearch/jsonmapper` and
// `phpdocumentor/reflection-docblock`. The latter is transitive
// dependency of `felixfbecker/advanced-json-rpc`
$required_extensions = [
'dom',
'filter',
'json',
'libxml',
'pcre',
'reflection',
'simplexml',
'spl',
'tokenizer',
];

@weirdan
Copy link
Collaborator

weirdan commented Feb 19, 2023

Another thing you may try is stopping Psalm from enabling JIT by running it with PSALM_ALLOW_XDEBUG=1 vendor/bin/psalm

@tarlepp
Copy link
Contributor Author

tarlepp commented Feb 19, 2023

Another update, this happens when I run Psalm inside docker container - if I run that same with host machine it works as expected.

PHP extenstions on that docker machine:

dev@php-fpm /app (chore(deps)/dependency-update)> php -m
[PHP Modules]
apcu
bcmath
Core
ctype
curl
date
dom
fileinfo
filter
ftp
hash
iconv
igbinary
intl
json
libxml
mbstring
mysqlnd
openssl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
posix
random
readline
Reflection
session
SimpleXML
sodium
SPL
sqlite3
standard
tokenizer
xdebug
xml
xmlreader
xmlwriter
Zend OPcache
zip
zlib

[Zend Modules]
Xdebug
Zend OPcache

dev@php-fpm /app (chore(deps)/dependency-update)>

And PHP extensions on my host machine:

tle@morko-virtualbox:~$ php -m
[PHP Modules]
calendar
Core
ctype
curl
date
dom
exif
FFI
fileinfo
filter
ftp
gettext
hash
iconv
intl
json
libxml
mbstring
openssl
pcntl
pcre
PDO
Phar
posix
random
readline
Reflection
session
shmop
SimpleXML
sockets
sodium
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
xml
xmlreader
xmlwriter
xsl
Zend OPcache
zlib

[Zend Modules]
Zend OPcache

tle@morko-virtualbox:~$ 

Hmm with that

Another thing you may try is stopping Psalm from enabling JIT by running it with PSALM_ALLOW_XDEBUG=1 vendor/bin/psalm

It seems to work as expected

dev@php-fpm /app (chore(deps)/dependency-update)> PSALM_ALLOW_XDEBUG=1 ./vendor/bin/psalm src/Controller/IndexController.php

Install the opcache extension to make use of JIT on PHP 8.0+ for a 20%+ performance boost!

Target PHP version: 8.2 (inferred from current PHP version) Enabled extensions: pdo.
Scanning files...
Analyzing files...

░

To whom it may concern: Psalm cannot detect unused classes, methods and properties
when analyzing individual files and folders. Run on the full project to enable
complete unused code detection.
------------------------------
                              
       No errors found!       
                              
------------------------------

Checks took 9.89 seconds and used 318.176MB of memory
Psalm was able to infer types for 100% of the codebase
dev@php-fpm /app (chore(deps)/dependency-update)> 

What might be the cause that this worked without that PSALM_ALLOW_XDEBUG on version 5.6 and with 5.7 it just crashes?

@weirdan
Copy link
Collaborator

weirdan commented Feb 19, 2023

Try commenting out these lines:

'-dopcache.enable_cli=true',
'-dopcache.jit_buffer_size=512M',
'-dopcache.jit=1205',

and running without PSALM_ALLOW_XDEBUG=1

@tarlepp
Copy link
Contributor Author

tarlepp commented Feb 19, 2023

Try commenting out these lines:

'-dopcache.enable_cli=true',
'-dopcache.jit_buffer_size=512M',
'-dopcache.jit=1205',

and running without PSALM_ALLOW_XDEBUG=1

Yeah it works when I commented out those lines.

@weirdan
Copy link
Collaborator

weirdan commented Feb 19, 2023

@danog any ideas?

@danog
Copy link
Collaborator

danog commented Feb 19, 2023

If you find a way to reproduce the issue consistently with a subset of your code (or link to it if it's FOSS), please open an issue @ https://github.com/php/php-src/issues, or otherwise send the code that triggers the segfault here (or try making a https://psalm.dev reproducer) so we can open an issue with proper gdb backtraces ourselves.

This would really be of great help to the PHP developers :)

@tarlepp
Copy link
Contributor Author

tarlepp commented Feb 19, 2023

And it looks like that following cases works:

 '-dopcache.enable_cli=true', 
 '-dopcache.jit_buffer_size=512M', 
// '-dopcache.jit=1205', 
 '-dopcache.enable_cli=true', 
// '-dopcache.jit_buffer_size=512M', 
 '-dopcache.jit=1205', 
// '-dopcache.enable_cli=true', 
 '-dopcache.jit_buffer_size=512M', 
 '-dopcache.jit=1205', 

So if all of those three options are set then this happen.

@weirdan
Copy link
Collaborator

weirdan commented Feb 19, 2023

// '-dopcache.jit=1205',

This one is of particular interest. Disabling any of the others just disables the JIT.

@danog
Copy link
Collaborator

danog commented Feb 19, 2023

@tarlepp Could you try reproducing the crash on psalm.dev, or at least send the contents of src/Controller/IndexController.php, if you can?

Edit: nevermind psalm.dev doesn't have JIT enabled, can you just try creating a Dockerfile that reproduces the issue?

@tarlepp
Copy link
Contributor Author

tarlepp commented Feb 19, 2023

@tarlepp Could you try reproducing the crash on psalm.dev, or at least send the contents of src/Controller/IndexController.php, if you can?

It doesn't matter which file I try to analyze with Psalm, but the contents of that IndexController.php is just:

<?php
declare(strict_types = 1);

namespace App\Controller;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Annotation\Route;

#[AsController]
class IndexController
{
    #[Route(
        path: '/',
        methods: [Request::METHOD_GET],
    )]
    public function __invoke(): JsonResponse
    {
        return new JsonResponse();
    }
}

@danog
Copy link
Collaborator

danog commented Feb 19, 2023

Could you try running with --debug-by-line, and what version of PHP are you using?
Could you try sending the dockerfile?

@tarlepp
Copy link
Contributor Author

tarlepp commented Feb 19, 2023

Could you try running with --debug-by-line

That didn't change the results

and what version of PHP are you using?

8.2.3

Could you try sending the dockerfile?

I created example repository where this can reproduced - https://github.com/tarlepp/psalm-issue

@weirdan
Copy link
Collaborator

weirdan commented Feb 19, 2023

Does JIT work for you at all? I.e. what does the following command produce?

php -dopcache.enable_cli=true -dopcache.jit_buffer_size=512M -dopcache.jit=1205 -r 'var_dump(opcache_get_status()["jit"]); '

@tarlepp
Copy link
Contributor Author

tarlepp commented Feb 19, 2023

Does JIT work for you at all? I.e. what does the following command produce?

php -dopcache.enable_cli=true -dopcache.jit_buffer_size=512M -dopcache.jit=1205 -r 'var_dump(opcache_get_status()["jit"]); '

If I run that command in that example repository I get following:

root@071981653ed6:/app# php -dopcache.enable_cli=true -dopcache.jit_buffer_size=512M -dopcache.jit=1205 -r 'var_dump(opcache_get_status()["jit"]); '

Warning: JIT is incompatible with third party extensions that override zend_execute_ex(). JIT disabled. in Unknown on line 0
Xdebug: [Step Debug] Could not connect to debugging client. Tried: 127.0.0.1:9003 (through xdebug.client_host/xdebug.client_port).
Command line code:1:
array(7) {
  'enabled' =>
  bool(false)
  'on' =>
  bool(false)
  'kind' =>
  int(0)
  'opt_level' =>
  int(5)
  'opt_flags' =>
  int(6)
  'buffer_size' =>
  int(0)
  'buffer_free' =>
  int(0)
}
root@071981653ed6:/app# 

@weirdan
Copy link
Collaborator

weirdan commented Feb 19, 2023

And what if you disable Xdebug in your php.ini?

@tarlepp
Copy link
Contributor Author

tarlepp commented Feb 19, 2023

And what if you disable Xdebug in your php.ini?

If Xdebug is disabled Psalm runs as expected. That is quite easy to test with that example repository, just edit that php-dev.ini file and build container again.

@weirdan
Copy link
Collaborator

weirdan commented Feb 19, 2023

No, I mean php -dopcache.enable_cli=true -dopcache.jit_buffer_size=512M -dopcache.jit=1205 -r 'var_dump(opcache_get_status()["jit"]); ', but with Xdebug disabled.

@tarlepp
Copy link
Contributor Author

tarlepp commented Feb 19, 2023

No, I mean php -dopcache.enable_cli=true -dopcache.jit_buffer_size=512M -dopcache.jit=1205 -r 'var_dump(opcache_get_status()["jit"]); ', but with Xdebug disabled.

Oh, sorry - that output is:

root@2cfd3c9faf68:/app# php -dopcache.enable_cli=true -dopcache.jit_buffer_size=512M -dopcache.jit=1205 -r 'var_dump(opcache_get_status()["jit"]); '

Warning: JIT is incompatible with third party extensions that override zend_execute_ex(). JIT disabled. in Unknown on line 0
Command line code:1:
array(7) {
  'enabled' =>
  bool(false)
  'on' =>
  bool(false)
  'kind' =>
  int(0)
  'opt_level' =>
  int(5)
  'opt_flags' =>
  int(6)
  'buffer_size' =>
  int(0)
  'buffer_free' =>
  int(0)
}
root@2cfd3c9faf68:/app#

@danog
Copy link
Collaborator

danog commented Feb 19, 2023

Strangely enough, it doesn't seem to be related to xdebug, but just to opcache.

Runnning psalm with this php.ini causes a segfault:

zend_extension=opcache.so
opcache.optimization_level="0"
opcache.enable_cli=1
opcache.jit_buffer_size=512M
opcache.jit=1205

Command:

php -n -c php.ini ./psalm --no-cache

Xdebug is disabled.

@danog
Copy link
Collaborator

danog commented Feb 19, 2023

It seems like opcache.optimization_level is actually set to 0 by the xdebug extension, so just disabling it fixes the issue, keeping the default value of 0x7FFEBFFF.

@weirdan
Copy link
Collaborator

weirdan commented Feb 19, 2023

The funny thing is, PHP manages to enter the body of a foreach that iterates over an empty array here:

psalm/src/Psalm/Config.php

Lines 1002 to 1004 in d934875

foreach ($deprecated_elements as $deprecated_element) {
$deprecated_elements_xml = $dom_document->getElementsByTagNameNS(
self::CONFIG_NAMESPACE,

The dump shown below added to that loop

 var_dump(
         'array is empty' , $deprecated_elements === [],
         'array' , $deprecated_elements,
         'element of that array' , $deprecated_element,
         '---------------'
 );

prints

string(14) "array is empty"
bool(true)
string(5) "array"
array(0) {
}
string(21) "element of that array"
UNKNOWN:0
string(15) "---------------"
string(14) "array is empty"
bool(true)
string(5) "array"
array(0) {
}
string(21) "element of that array"
UNKNOWN:0
string(15) "---------------"
Segmentation fault (core dumped)

weirdan added a commit that referenced this issue Feb 19, 2023
Always use 0x7FFEBFFF opcache optimization level (fixes #9340)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants