phppthreadsextending-classes

PHP Bug in threaded environment assigning value to parent static member in same thread?


I have this issue where I wonder if it is a PHP bug or intentional behaviour. If I assign in the child class a MySQL resource to a parent member then the value gets lost when running as a thread.

This code does not run - the MySQL resource should be displayed twice:

<?php
class MyFileAbstract extends Threaded
{
    protected static $m_Connection;
    public static function init() {
        static::openFile();
        echo "<br>Member accessed from parent: ";
        print_r(self::$m_Connection);   # the resource is empty
    }
}

class MyFile extends MyFileAbstract
{
    public static function openFile() {
        self::$m_Connection = fopen("/etc/php.ini", "r");
        echo "<br>Member accessed from child: ";
        print_r(self::$m_Connection)."<br>";   # the resource has value
    }
}

class MyThread extends Thread
{
    public function run() {
        MyFile::init();
    }

}

$myThread = new MyThread();
$myThread->start();
echo "<br>Correct output:";
MyFile::init();
?>

This is the result - expected output for "Member accessed from parent:" should be something like "Resource id#2":

Member accessed from child: Resource id #2
Member accessed from parent:
Correct output:
Member accessed from child: Resource id #3
Member accessed from parent: Resource id #3

I have to change it and then the member $m_Connection receives/keeps the resource from fopen(). Note: It is working in the thread!

<?php
class MyFileAbstract extends Threaded
{
    protected static $m_Connection;
    public static function openFile()
    {
        $sFileName = static::getFileName();
        self::$m_Connection = fopen($sFileName, "r");
        echo "Member accessed from parent: ";
        print_r(self::$m_Connection);   # the resource has value
    }
}

class MyFile extends MyFileAbstract
{
    public static function getFileName()
    {
        return "/etc/php.ini";
    }
}

class MyThread extends Thread
{
    public function run()
    {
        MyFile::openFile();
    }
}

$myThread = new MyThread();
$myThread->start();
?>

Output:

Member accessed from parent: Resource id #2

Requirements to run the examples:

  1. PHP compiled with enabled Thread Safety
  2. PHP compiled with the pThread library

I have to connect to MySql in the thread according to this article: http://php.net/manual/en/intro.pthreads.php

UPDATE:

I changed the code: it is opening /etc/php.ini instead of connecting to MySql database. Same result --> the resource gets lost when returning it from the extended class. The examples are now running 1:1 without changing/adapting anything.


Solution

  • I still think it is a bug. I found now a workaround, when the resource is explicitly assigned to the class member in the openFile() function as parent:: and not as self:::

    <?php
    class MyFileAbstract extends Threaded
    {
        protected static $m_Connection;
        public static function init() {
            static::openFile();
            echo "<br>Member accessed from parent: ";
            print_r(self::$m_Connection);   # the resource is empty
        }
    }
    
    class MyFile extends MyFileAbstract
    {
        public static function openFile() {
            # the resource keeps now the value when using parent:: instead of self::
            parent::$m_Connection = fopen("/etc/php.ini", "r");
            echo "<br>Member accessed from child: ";
            print_r(parent::$m_Connection)."<br>";
        }
    }
    
    class MyThread extends Thread
    {
        public function run() {
            MyFile::init();
        }
    
    }
    
    $myThread = new MyThread();
    $myThread->start();
    echo "<br>Correct output:";
    MyFile::init();
    ?>
    

    The result is now correct:

    Member accessed from child: Resource id #2
    Member accessed from parent: Resource id #2
    Correct output:
    Member accessed from child: Resource id #3
    Member accessed from parent: Resource id #3