pthreads icon indicating copy to clipboard operation
pthreads copied to clipboard

Serialization of 'Closure' is not allowed in Worker

Open landall opened this issue 5 years ago • 5 comments

Environment

PHP 7.2.19 (cli) (built: May 29 2019 14:17:01) ( ZTS MSVC15 (Visual C++ 2017) x86 ) Pthread 3.2.0 Win10 x64

Summary

When I assign a object with a member of GuzzleHttp\Client to a field of my worker class, I raise an exception saying Serialization of 'Closure' is not allowed.

Reproducing Code

class TaskQueueWorker extends \Worker { public function __construct($client) { $this->client = $client; }

public static $client;

}

$client is an object of a class with a sub object of GuzzleHttp\Client.

Its package information: "name": "guzzlehttp/guzzle", "version": "6.3.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", "shasum": "" }, "require": { "guzzlehttp/promises": "^1.0", "guzzlehttp/psr7": "^1.4", "php": ">=5.5" },

Expected Output

Actual Output

raise a fatal error.

landall avatar Jun 19 '19 19:06 landall

also happened in CentOS 7 with remi-php7.2 rpm packages. PHP 7.2.19 (cli) (built: May 29 2019 11:10:45) ( ZTS )

Installed Packages php.x86_64 7.2.19-2.el7.remi @remi-php72 php-cli.x86_64 7.2.19-2.el7.remi @remi-php72 php-common.x86_64 7.2.19-2.el7.remi @remi-php72 php-json.x86_64 7.2.19-2.el7.remi @remi-php72 php-pecl-pthreads.x86_64 3.2.0-1.el7.remi.7.2 @remi-php72

landall avatar Jun 19 '19 19:06 landall

The properties of the instances that inherit from Threaded are serialized so that the information they host can be passed between contexts.

When you pass your http client to your worker, the engine tries to serialize the instance of GuzzleHttp\Client and at some point you will find an anonymous function or closure. Anonymous functions cannot be serialized due to their nature. It's like trying to do:

$result = serialize(function () {});

That will throw a fatal error: Serialization of 'Closure' is not allowed

If you want to create an instance that is shared by all the threads of your worker you can do the following.

<?php

use Worker;

class TaskQueueWorker extends Worker
{
    protected static $client;

    public function run()
    {
        // It is necessary to call the autoload composer file, since the context
        // of the worker is new and does not have the spl autoload function
        // for psr-4
        require 'vendor/autoload.php';
    }

    public function getClient()
    {
        if (self::$client) {
            return self::$client;
        }

        self::$client = new GuzzleHttp\Client();

        return self::$client;
    }
}

You can learn more about how to share objects in the examples: https://github.com/krakjoe/pthreads/blob/master/examples/MySQLi.php

AlexSayHello avatar Aug 06 '19 19:08 AlexSayHello

@AlexSayHello That isn't sharing. Statics are thread-local, not shared.

dktapps avatar Aug 06 '19 19:08 dktapps

@dktapps When I refer to "shared" I mean that the instance is available from the thread through $this->worker->getClient(). Maybe I have not used the most appropriate concept to describe it. I wasn't referring to sharing data.

AlexSayHello avatar Aug 06 '19 19:08 AlexSayHello

Does this means I must create the instance as a thread-local object if it uses an anonymous function or closure? I cannot control the code from others' package.

landall avatar Aug 07 '19 03:08 landall