m6w6 / ext-http

Extended HTTP Support
BSD 2-Clause "Simplified" License
79 stars 22 forks source link

http\Client::enqueue(): Could not enqueue request: The easy handle is already added to a multi handle #65

Closed rcanavan closed 7 years ago

rcanavan commented 7 years ago

If one attempts to exit() a PHP program from within the setDebug() callback of a http\Client, a Warning is emitted:

PHP Warning:  Unknown: Could not dequeue request while executing callbacks in Unknown on line 0

If the Client uses a persistent handle, enqueuing a new request, even from a subsequent incoming client request in the same PHP / PHP-FPM child, this fails with a fatal error:

PHP Fatal error:  Uncaught http\Exception\RuntimeException: http\Client::enqueue(): Could not enqueue request: The easy handle is already added to a multi handle in pecl_http_crash.php:25
Stack trace:
#0 pecl_http_crash.php(25): http\Client->enqueue(Object(http\Client\Request), Object(Closure))
#1 {main}
  thrown in pecl_http_crash.php on line 25

Test program:

<?php
class test implements SplObserver {
    function update(SplSubject $client) {
        $client->once();
    }

    public function updateDebugData(http\Client\Request $request, int $type, string $data)
    {
        if (strpos($data, 'left intact') > 0) {
            error_log('It's the end allready, exiting!');
            exit;
        }
    }
}

$client = new http\Client('curl', 'persist!');
$client->attach(new test);
$client->enqueue(new http\Client\Request("GET", "http://localhost:14080/slow.php"), function($r) {
    var_dump($r->getResponseCode());
});
$client->setDebug(function(http\Client $client, http\Client\Request $request, int $type, string $data) {
    foreach ($client->getObservers() as $observer) {
        $observer->updateDebugData($request, $type, $data);
    }
});

$client->send();

The obvious solution is not to use exit() in the debug callback, but there may be more legitimate ways to trigger this. To trigger the problem, it may be necessary to call the test program above in a tight loop, e.g.

while true; do curl localhost:14080/pecl_http_reuse_bug.php; done
m6w6 commented 7 years ago

Works for me(tm). IIRC, this is fixed in newer PHP versions. No warning here with PHP-7.1.2 locally.

m6w6 commented 7 years ago

Hah, the warning's just been put in the error log.

m6w6 commented 7 years ago

Could you try the following patch, please? issue65.txt

rcanavan commented 7 years ago

No warning here with PHP-7.1.2 locally.

I'm using PHP 7.1.3. Today the errors appear to be more or less permanent, and only a restart of PHP-FPM allows me to process requests with the "broken" persistent handle. With the patch, no warnings are printed and all requests are apparently handled successfully.

m6w6 commented 7 years ago

Awesome, thank you!