pmmp / ext-pmmpthread

Fork of https://github.com/krakjoe/pthreads with a revamped API and PHP 8.1+ support
Other
81 stars 17 forks source link

Fake closures (or first-class callables) don't reference the correct static variables #99

Closed dktapps closed 1 year ago

dktapps commented 1 year ago

Calling a first-class callable is identical in behaviour to calling the function directly, and shares the same static variables.

pthreads doesn't currently respect this, and each copied first-class callable ends up with its own copy of the static variables, breaking behaviour.

class A{
    public static function test() : void{
        static $a = 0;
        $a++;
        var_dump("a = $a");
    }
}

function test(\Closure $fcc) : void{
    $fcc();
    A::test();
}

$fcc = \Closure::fromCallable([A::class, 'test']);
test($fcc);
echo "end\n";
$t = new class($fcc) extends \Thread{
    private \Closure $fcc;

    public function __construct(\Closure $fcc){
        $this->fcc = $fcc;
    }

    public function run() : void{
        test($this->fcc);
    }
};
$t->start();
$t->join();

This should output

string(5) "a = 1"
string(5) "a = 2"
end
string(5) "a = 1"
string(5) "a = 2"

but actually outputs

string(5) "a = 1"
string(5) "a = 2"
end
string(5) "a = 1"
string(5) "a = 1"
dktapps commented 1 year ago

Turns out that fake closures may also refer to other closures, where the behaviour is similar (the original closure's static variables are shared with the fake closure created by Closure::fromCallable()).