Skip to content

Odd behaviour resulting in SIGSEGV  #129

Open
@beeradmoore

Description

@beeradmoore

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();

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions