jrgp/linfo

Library doesn't work with PHP7.1

cedricve opened this issue · 38 comments

When trying to run the library on a PHP 7.1 installation it goes in an infinite loop. Not sure what's going wrong.

I confirm it works properly with 7.0

jrgp commented

Any errors in logs?

jrgp commented

which OS is this?

@jrgp Ubuntu 16.4 (docker container). Well no error logs, It's look like when using the Linux OS class, and entering the parser method. CPU goes 100%.

I can confirm this. Use docker 17.06.0 on Mac, running ubuntu:xenial with PHP7.1 from ppa:ondrej/php

Running ./linfo-dev-server, opening browser to see the result, it took so long and return nothing.

I'm not sure it's only happened on Docker container or also in real server (VPS, hosting). Will try it.

jrgp commented

Kinda weird. I should do testing on my end as well. One thing you can do is selectively disable panels in the config file to see which one is the bad one. Enabling the timer as well could help.

jrgp commented

I can't repro this on an Ubuntu Xenial container under LXC running stock apache/mod_php PHP 7.0.18-0ubuntu0.16.04.1 from apt.

@jrgp Here the method I used to reproduce.

docker run -it --rm -p 8081:8081 -v $PWD:/www ubuntu:xenial bash

Inside docker container, I ran these commands.

apt-get update
apt-get install software-properties-common
add-apt-repository ppa:ondrej/php
apt-get update
apt-get install php7.1
cd /www
./linfo-dev-server

I opened the browser, hit http://localhost:8081 and it take so long to show. In the console there's nothing shown up.

PHP 7.1.7-1+ubuntu16.04.1+deb.sury.org+1 Development Server started at Thu Aug  3 10:42:42 2017
Listening on http://0:8081
Document root is /www
Press Ctrl-C to quit.

Using PHP 7.0, it ran normally.

after trying in CentOS 7 and Ubuntu 16.10 (both ran as Docker container), the problem I think is in the PHP 7.1 from ondrej/php repo (need more prove).

in CentOS 7 using PHP 7.1 from Webtatic repo, Linfo ran without any problem.

PHP 7.1.7 in archlinux. Confirm this problem.

Using Nginx + PHP 7.1 FPM in Ubuntu Xenial (Docker container) was also failed. Using PHP 7.0 FPM in the same container was successful.

jrgp commented

Should probably strace the php process while this problem is happening so we can get an idea of what it is chewing on.

gemal commented

same on amazon ec2 php 7.1 with nginx

gemal commented

this is the problem:
$linfo = new Linfo($settings);

if you die() just after this it never reaches this die

@jrgp do you have any update on this? Looks like some people are having issues with this, and is limiting upgrading PHP to 7.1. Thanks again for your amazing work! I heavily use your library in the web interface of @kerberos-io.

jrgp commented

I'll try to take a look at this today. Really sorry for the inconvenience!

amazing @jrgp thanks!

jrgp commented

Can't repro on ubuntu trusty and locally compiled latest php.

joe@fireball:~/fix_linfo/linfo$ ../php/bin/php -v
PHP 7.1.8 (cli) (built: Aug 16 2017 01:33:49) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
joe@fireball:~/fix_linfo/linfo$ ../php/bin/php test.php | head
array(24) {
  [0]=>
  array(3) {
    ["Vendor"]=>
    string(12) "GenuineIntel"
    ["Model"]=>
    string(47) "Intel(R) Xeon(R) CPU           X5650  @ 2.67GHz"
    ["MHz"]=>
    string(8) "2660.126"
  }
joe@fireball:~/fix_linfo/linfo$

Granted this isn't in a container; it's on a bare metal host.

I'll try to repro elsewhere.

jrgp commented

Can't repro on 7.1.7 either (the version you guys are using)

joe@fireball:~/fix_linfo/linfo$ ../php717/bin/php -v
PHP 7.1.7 (cli) (built: Aug 16 2017 01:44:29) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

joe@fireball:~/fix_linfo/linfo$ ../php717/bin/php test.php |head
array(24) {
  [0]=>
  array(3) {
    ["Vendor"]=>
    string(12) "GenuineIntel"
    ["Model"]=>
    string(47) "Intel(R) Xeon(R) CPU           X5650  @ 2.67GHz"
    ["MHz"]=>
    string(8) "2660.126"
  }

It's gotta be something specific to running under a container. I'll be digging into this more. Maybe see if I can repo on mac.

jrgp commented

I'm going to try under xenial/docker/ondrej

jrgp commented

Aha! I can repro under docker. Will investigate and release a fix.

jrgp commented

Disabling opcache "fixes" it. Eg comment out the line in /etc/php/7.1/mods-available/opcache.ini

Seems to be related to https://bugs.php.net/bug.php?id=72112

Last output from strace when it hangs:

30645 stat("/www/src/Linfo/OS/Linux.php", {st_mode=S_IFREG|0644, st_size=58328, ...}) = 0
30645 --- SIGPROF {si_signo=SIGPROF, si_code=SI_KERNEL} ---
jrgp commented

Can confirm php7.2 from ondrej dies the same way and disabling opcache (/etc/php/7.2/mods-available/opcache.ini) fixes it.

jrgp commented

Need to figure out whether it's:

  1. bug in opcache
  2. bug in the way ondrej compiles php
  3. either of the above + requirement for running inside a container

And:

  1. whether there's a config tweak that can fix it aside from completely disabling opcache

Either way, I think it's the fault of PHP here rather than linfo itself. I'm going to dig deeper and look into a "better" fix for this though.

@jrgp amazing find. Do you usie any caching in the Linfo library?

jrgp commented

@cedricve not really.

The opcache module is for transparently caching the compiled bytecode of each .php file itself to make PHP apps with a large number of files (i.e. most modern ones) run faster. It's the modern day replacement of old similar modules like apc/apcu and others.

I debug'd this issue using the echo 'foo' ; exit; method and I identified the call which hung is in Linfo.php on line 88 where the Linux class is loaded, which triggers the PHP class autoloader which is when that stat call from the strace output is printed and which is when the PHP process hangs.

Can we repro this using PHP not from ondrej ?

@jrgp that makes sense, I'll give it a try to get it compiled in my dockerfile with another distro. Keep you posted! Any suggestions for other repos @jrgp?

https://github.com/kerberos-io/docker/blob/master/base/Dockerfile#L29

I used Sergey's PPA add-apt-repository ppa:sergey-dryabzhinsky/php71 and install it using apt-get install php71p-cli. Linfo run smoothly.

Then I installed Opcache using apt-get install php71p-mod-opcache and the problem occured. I think the problem is in the opcache.

For temporary, it would be better to inform by adding the Opcache note ini PHP 7.1 in the README.

thanks @matriphe, ok let me try that one. I don't need opcache, so this isn't an issue for me, but I can imagine that there will be some people relying on opcache heavily. For now we can add it to the README, but we really need to find out why this is happening, also can't imagine that there would be an major bug in the opcache library. I think that some code of the Linfo library doesn't get optimized properly and causing this infinite loop. So I assume there is something weird going in here, but what will be a hard (but interesting) thing to resolve.

@cedricve yes. Opcache is running safely in PHP 7.0 and below. I think disabling Opcache in PHP 7.1 is a best practice for now.

thanks for the share @matriphe I'll do that!

jrgp commented

I just added the opcache caveat to the README file.

I tried a bunch of different ways of fixing this (manually changing each opcache option, one by one, to see if it fixed it) but I haven't been successful.

Will be worth seeing if it still is broken in upcoming php releases. Maybe 7.3 will be better.

Before the problem is solved, we can use the opcache.blacklist_filename option to avoid this problem.

jrgp commented

^ That's a really good idea.

jrgp commented

Oh I was hoping that opcache.blacklist_filename was ini_set()'able and took a path (like __DIR__) as its argument. As it requires a text file with paths I can't really use it inside linfo itself, but rather just suggest people use it to avoid disabling opcache altogether.

hey guys, any update on this? We are few months further.

jrgp commented

I'll take another look into this and see if I can fix it.

jrgp commented

I looked into this a bit more. I can't currently reproduce this under ondrej php7.1 or php7.2 because this was caused by this upstream bug ( https://bugs.php.net/bug.php?id=75255 ) which was fixed in versions of php after 7.1.9, and ondrej has since updated to php 7.1.14

I'm going to close this as updating to at least PHP 7.1.11 fixes this, and it's likely that PPAs and distros have moved past the bad version at this point.