Closed dktapps closed 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"
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()).
Closure::fromCallable()
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.
This should output
but actually outputs