amphp / amp

A non-blocking concurrency framework for PHP applications. 🐘
https://amphp.org/amp
MIT License
4.21k stars 255 forks source link

UVLoop handle is already closed error with basic parallel example #300

Open roquie opened 4 years ago

roquie commented 4 years ago

Code to reproduce (extension uv.so must be enabled):

use Amp\Parallel\Worker;
use Amp\Promise;

$urls = [
    'https://secure.php.net',
    'https://amphp.org',
    'https://github.com',
];

$promises = [];
foreach ($urls as $url) {
    $promises[$url] = Worker\enqueueCallable('file_get_contents', $url);
}

$responses = Promise\wait(Promise\all($promises));

foreach ($responses as $url => $response) {
    \printf("Read %d bytes from %s\n", \strlen($response), $url);
}

throw new Exception('asd');

Output with infinity loop:

Warning: uv_run(): passed UVLoop handle is already closed in /Users/roquie/google_drive/projects/ioteamc/reportmaker/vendor/amphp/amp/lib/Loop/UvDriver.php on line 190

Call Stack:
    0.8706    3505616   1. Amp\Parallel\Worker\TaskWorker::Amp\Parallel\Worker\{closure:/Users/roquie/google_drive/projects/ioteamc/reportmaker/vendor/amphp/parallel/lib/Worker/TaskWorker.php:44-63}() /Users/roquie/google_drive/projects/ioteamc/reportmaker/vendor/amphp/parallel/lib/Worker/TaskWorker.php:0
    0.8709    3515184   2. Amp\Promise\wait() /Users/roquie/google_drive/projects/ioteamc/reportmaker/vendor/amphp/parallel/lib/Worker/TaskWorker.php:57
    0.8709    3515976   3. Amp\Loop::run() /Users/roquie/google_drive/projects/ioteamc/reportmaker/vendor/amphp/amp/lib/functions.php:191
    0.8709    3516576   4. Amp\Loop\UvDriver->run() /Users/roquie/google_drive/projects/ioteamc

Other info:

PHP 7.4.0 (cli) (built: Nov 29 2019 16:18:30) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Xdebug v2.9.0, Copyright (c) 2002-2019, by Derick Rethans
    with Zend OPcache v7.4.0, Copyright (c), by Zend Technologies
roquie@roquies-MacBook-Pro:~/google_drive/projects/ioteamc/reportmaker$ composer info | grep amphp
amphp/amp                          v2.4.1             A non-blocking concurrency framework for PHP applications.
amphp/byte-stream                  v1.7.2             A stream abstraction to make working with non-blocking I/O simple.
amphp/file                         v1.0.0             Allows non-blocking access to the filesystem for Amp.
amphp/parallel                     v1.2.0             Parallel processing component for Amp.
amphp/parallel-functions           v0.1.3             Parallel processing made simple.
amphp/parser                       v1.0.0             A generator parser to make streaming parsers simple.
amphp/process                      v1.1.0             Asynchronous process manager.
amphp/sync                         v1.3.0             Mutex, Semaphore, and other synchronization tools for Amp.

MacOS Catalina 10.15.3

P.S. With disabled xdebug problem will still alive.

kelunik commented 4 years ago

Thank you for the report, I can reproduce the issue.

kelunik commented 4 years ago

This is caused by a register_shutdown_function callback, seems like UV automatically closes handles too early.

enumag commented 4 years ago

Is it a bug in ext-uv then?

kelunik commented 4 years ago

Either that or within PHP itself. According to @bwoebi it's reproducible on PHP 7.4, but not with master. Could you open a report at the ext-uv repository?

cmp-nct commented 3 years ago

I've a similar problem, though in my case it's a normal loop, I was not able to reproduce it easily. In my case I run my loop and it runs fine for 12+ hours, suddenly I am getting that Warning message (millions of them). It does not happen with the default loop implementation, that runs for 2+ weeks stable in identical code. I'll switch back to the default loop.

If I had my output into a logfile the error messages would have filled up the diskspace. I've no idea what triggers the error (looks like an internal bug to me) but it should throw a Error not a Warning. So the thing doesn't go "crazy" when it happens.

uv_run($loop = class UVLoop { }, $run_mode = 1) PHP Warning: uv_run(): passed UVLoop handle is already closed in src/ExtUvLoop.php on line 231