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

Odd behaviour resulting in SIGSEGV #129

Open
beeradmoore opened this issue Apr 28, 2023 · 3 comments · May be fixed by #132
Open

Odd behaviour resulting in SIGSEGV #129

beeradmoore opened this issue Apr 28, 2023 · 3 comments · May be fixed by #132

Comments

@beeradmoore
Copy link

beeradmoore commented Apr 28, 2023

TL;DR; Weird thing happens with php8+ when using Amazon Linux 2. Using docker images from php for php8+ the same test pasts. Issue appears to be related to the specific packages installed not php as a whole. BUT it does also show some odd things happening by moving code about.

I'm not sure how to debug php-meminfo itself, but I have a really odd one that I was able to replicate down to a small test. The test consists of TestClass in which I want to use the static Current() method to get a single instance of the class.

<?php

class TestClass
{
	protected static $CurrentInstance;
	
    public static function Current() : TestClass
    {
		// Check if there is an instance created already.
        if (isset(static::$CurrentInstance))
        {
            return static::$CurrentInstance;
        }

		// If not create and return it.
		static::$CurrentInstance = new TestClass();
        
        return static::$CurrentInstance;
	}
}

$some_bool = false;

if ($some_bool === true)
{
	$test = TestClass::Current();	
}

meminfo_dump(fopen('/tmp/my_dump_file.json', 'w'));

echo time();

This will result in SIGSEGV which will result in apache giving a 503 response. But things get really odd really quick.

If you change

if ($some_bool === true)
{
	$test = TestClass::Current();	
}

to

if ($some_bool === true)
{
	TestClass::Current();	
}

then the code will work. Maybe something about having a reference to the variable? But it's odd because the code will never execute as $some_bool is false.

Another oddity is if you move the declaration outside of the if then it will also work as expected.

$test = TestClass::Current();

if ($some_bool === true)
{

}

EDIT: I also just found it has nothing to do with the static variable. The new minimum test case is

<?php

class TestClass
{
	
}

$some_bool = false;

if ($some_bool === true)
{
	$test = new TestClass();
}

meminfo_dump(fopen('/tmp/my_dump_file.json', 'w'));

echo time();

I should have also included specs. This is running on a Amazon Linux 2 EC2 instance. php version is

# php -v
PHP 8.0.28 (cli) (built: Mar 28 2023 17:41:50) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.28, Copyright (c) Zend Technologies
    with Zend OPcache v8.0.28, Copyright (c), by Zend Technologies

As for php-meminfo, I built it from the current master source.

EDIT 2:

This can be replicated without the TestClass

<?php

$some_bool = false;

if ($some_bool === true)
{
	$test = new stdClass();
}

meminfo_dump(fopen('/tmp/my_dump_file.json', 'w'));

echo time();

EDIT 3:
Looks like maybe it has something to do with code being removed when executed or something.

This works

<?php

$some_bool = false;

if ($some_bool === false)
{
	$test = new stdClass();
}

meminfo_dump(fopen('/tmp/my_dump_file.json', 'w'));

echo time();

This does not

<?php

$some_bool = false;

if ($some_bool === true)
{
	$test = new stdClass();
}

meminfo_dump(fopen('/tmp/my_dump_file.json', 'w'));

echo time();

But in saying that this works and it shouldn't according to the above example

<?php

$some_bool = true;

if (false)
{
	$test = new stdClass();
}

meminfo_dump(fopen('/tmp/my_dump_file.json', 'w'));

echo time();

But then this also works

<?php

$some_bool = false;

$test = null;
if ($some_bool === true)
{
	$test = new stdClass();
}

meminfo_dump(fopen('/tmp/my_dump_file.json', 'w'));

echo time();

You can also get this to fail with primatives.

<?php

$some_bool = false;
if ($some_bool === true)
{
	$test = 1;
}

meminfo_dump(fopen('/tmp/my_dump_file.json', 'w'));

echo time();
@beeradmoore
Copy link
Author

beeradmoore commented Apr 28, 2023

I created a Dockerfile which has a repo of this issue.

FROM amazonlinux:2.0.20230320.0

WORKDIR /meminfo/

# Update, install required tools
RUN yum update -y && \
    amazon-linux-extras install -y php8.0 && \
    yum install -y php-devel gcc make unzip

# Download and extract php-meminfo
RUN curl -L -o /meminfo/master.zip https://github.com/BitOne/php-meminfo/archive/refs/heads/master.zip
RUN unzip /meminfo/master.zip

# Install meminfo
RUN cd /meminfo/php-meminfo-master/extension && \
    phpize && \
    ./configure --enable-meminfo && \
    make && \
    make install && \
    echo "extension=meminfo.so" >> /etc/php.ini 

COPY test.php /meminfo/test.php

CMD ["php", "/meminfo/test.php"]

Where test.php is

<?php

$some_bool = false;

if ($some_bool === true)
{
	$test = new stdClass();
}

meminfo_dump(fopen('/tmp/my_dump_file.json', 'w'));

echo time();

Can be built with

docker build -t php-meminfo .

Can be ran with

docker run --rm php-meminfo:latest
If you see the time output then it worked, if no time is output it failed.

You can dig deeper into it by running (at least on macOS, for other OS you may need to change $PWD)

docker run -v $PWD/test.php:/meminfo/test.php --rm -it php-meminfo:latest /bin/sh

By modifying the php version installed I was able to confirm this test fails on php8.0 was able to confirm the test fails with the following php versions

PHP 8.0.28 (cli) (built: Mar 28 2023 17:41:50) ( NTS )
Copyright (c) The PHP Group
Zend Engine v4.0.28, Copyright (c) Zend Technologies
PHP 8.1.16 (cli) (built: Mar 23 2023 19:44:13) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.16, Copyright (c) Zend Technologies
PHP 8.2.3 (cli) (built: Mar 15 2023 21:12:07) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.3, Copyright (c) Zend Technologies

Modifying docker image from the php-meminfo-1.1.1 release I can test on php5 and can confirm it works.

PHP 5.4.16 (cli) (built: Oct 31 2019 18:34:05) 
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologies

This is the php5 Dockerfile for testing.

FROM amazonlinux:2.0.20230320.0

WORKDIR /meminfo/

# Update, install required tools
RUN yum update -y && \
    yum install -y php php-devel gcc make unzip

# Download and extract php-meminfo
RUN curl -L -o /meminfo/v1.1.1.zip https://github.com/BitOne/php-meminfo/archive/refs/tags/v1.1.1.zip
RUN unzip /meminfo/v1.1.1.zip

# Install meminfo
RUN cd /meminfo/php-meminfo-1.1.1/extension/php5/ && \
    phpize && \
    ./configure --enable-meminfo && \
    make && \
    make install && \
    echo "extension=meminfo.so" >> /etc/php.ini 

COPY test.php /meminfo/test.php

CMD ["php", "/meminfo/test.php"]

For some reason there is no php7.4 to test with 🤷‍♂️

EDIT:
Building from php docker image base I was able to get the test to pass with php7.4

FROM php:7.4-fpm

WORKDIR /meminfo/

# Update, install required tools
RUN apt update && apt upgrade -y && \
    apt install unzip -y

# Download and extract php-meminfo
RUN curl -L -o /meminfo/master.zip https://github.com/BitOne/php-meminfo/archive/refs/heads/master.zip
RUN unzip /meminfo/master.zip

# Install meminfo
RUN cd /meminfo/php-meminfo-master/extension && \
    phpize && \
    ./configure --enable-meminfo && \
    make && \
    make install && \
    cp /usr/local/etc/php/php.ini-development /usr/local/etc/php/php.ini && \
    echo "extension=meminfo.so" >> /usr/local/etc/php/php.ini

COPY test.php /meminfo/test.php

CMD ["php", "/meminfo/test.php"]

Updating to php8.2 to build from the test also passes. Which means there is something wrong/missing with the php from AWS.

@vtsykun
Copy link

vtsykun commented Feb 6, 2024

I have the same problem, I'll try to fix it

Program received signal SIGSEGV, Segmentation fault
0x00007ffff2b43fb6 in meminfo_browse_class_static_members (stream=stream@entry=0x7ffff54c2ee0, visited_items=visited_items@entry=0x7fffed5f8cf0, first_element=first_element@entry=0x7fffed5f8ce4)
    at /opt/progs/php-meminfo/extension/meminfo.c:147
147	        if (class_entry->default_static_members_count > 0 && CE_STATIC_MEMBERS(class_entry)) {
(gdb) bt 
#0  0x00007ffff2b43fb6 in meminfo_browse_class_static_members (stream=stream@entry=0x7ffff54c2ee0, visited_items=visited_items@entry=0x7fffed5f8cf0, first_element=first_element@entry=0x7fffed5f8ce4)
    at /opt/progs/php-meminfo/extension/meminfo.c:147
#1  0x00007ffff2b445be in zif_meminfo_dump (execute_data=<optimized out>, return_value=<optimized out>) at /opt/progs/php-meminfo/extension/meminfo.c:80
#2  0x00005555558a5d48 in execute_ex ()
#3  0x000055555582dcbc in zend_call_function ()
#4  0x00005555558d72c9 in ?? ()
#5  0x00005555558d82b2 in ?? ()
#6  0x00005555557d6287 in make_fcontext ()
#7  0x0000000000000000 in ?? ()

@DocDocTeam
Copy link

DocDocTeam commented Feb 6, 2024 via email

@vtsykun vtsykun linked a pull request Feb 17, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants