简体   繁体   English

致命错误使用Symfony控制台时打开文件过多

[英]Fatal Error too many open files when using Symfony Console

I'm running a console process that listens for an event and writes a . 我正在运行一个控制台进程,该进程监听一个事件并编写一个. to the console to indicate progress. 到控制台以指示进度。 This can run for 10-15 minutes, but by about 10 min I get the following series of fatal console errors: 这可以运行10-15分钟,但是到大约10分钟时,我收到以下一系列致命的控制台错误:

[2014-10-14 11:13:49] local.ERROR: 500 - fopen(php://stderr): failed to open stream: operation failed @ /
exception 'ErrorException' with message 'fopen(php://stderr): failed to open stream: operation failed' in /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Output/ConsoleOutput.php:53
Stack trace:
#0 [internal function]: Illuminate\Exception\Handler->handleError(2, 'fopen(php://std...', '/vagrant/www/te...', 53, Array)
#1 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Output/ConsoleOutput.php(53): fopen('php://stderr', 'w')
#2 /vagrant/www/test.dev/laravel/app/library/ecomevo/task/src/eComEvo/TaskRunner/Traits/Events.php(262): Symfony\Component\Console\Output\ConsoleOutput->__construct()
#3 [internal function]: eComEvo\TaskRunner\TaskRunner::eComEvo\TaskRunner\Traits\{closure}('.', 280, Array)
#4 /vagrant/www/test.dev/laravel/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php(199): call_user_func_array(Object(Closure), Array)
#5 /vagrant/www/test.dev/laravel/app/library/ecomevo/task/vendor/illuminate/support/Illuminate/Support/Facades/Facade.php(211): Illuminate\Events\Dispatcher->fire('task.group.prog...', Array)
#6 /vagrant/www/test.dev/laravel/app/library/ecomevo/task/src/eComEvo/TaskRunner/Traits/Events.php(92): Illuminate\Support\Facades\Facade::__callStatic('fire', Array)
#7 /vagrant/www/test.dev/laravel/app/library/ecomevo/task/src/eComEvo/TaskRunner/Traits/Events.php(92): Illuminate\Support\Facades\Event::fire('task.group.prog...', Array)
#8 /vagrant/www/test.dev/laravel/app/library/ecomevo/task/src/eComEvo/TaskRunner/Traits/Events.php(205): eComEvo\TaskRunner\TaskRunner::event('progress', '.', 280, '423403-23463321-604...', 'event')
#9 /vagrant/www/test.dev/laravel/app/models/TaskRunner.php(280): eComEvo\TaskRunner\TaskRunner::progress('.', 280, '2423-521354...')
#10 /vagrant/www/test.dev/laravel/app/library/ecomevo/task/src/eComEvo/TaskRunner/Commands/TaskRunnerImportOrdersCommand.php(128): TaskRunner::import('15', NULL, Array, '16', '4')
#11 /vagrant/www/test.dev/laravel/vendor/laravel/framework/src/Illuminate/Console/Command.php(112): eComEvo\TaskRunner\Commands\TaskRunnerImportOrdersCommand->fire()
#12 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Command/Command.php(252): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#13 /vagrant/www/test.dev/laravel/vendor/laravel/framework/src/Illuminate/Console/Command.php(100): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#14 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(889): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#15 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(193): Symfony\Component\Console\Application->doRunCommand(Object(eComEvo\TaskRunner\Commands\TaskRunnerImportOrdersCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#16 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(124): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#17 /vagrant/www/test.dev/laravel/artisan(59): Symfony\Component\Console\Application->run()
#18 {main} [] []
[2014-10-14 11:13:50] local.ERROR: 500 - proc_open(): unable to create pipe Too many open files @ /
exception 'ErrorException' with message 'proc_open(): unable to create pipe Too many open files' in /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php:983
Stack trace:
#0 [internal function]: Illuminate\Exception\Handler->handleError(2, 'proc_open(): un...', '/vagrant/www/te...', 983, Array)
#1 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(983): proc_open('stty -a | grep ...', Array, NULL, NULL, NULL, Array)
#2 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(799): Symfony\Component\Console\Application->getSttyColumns()
#3 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(760): Symfony\Component\Console\Application->getTerminalDimensions()
#4 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(690): Symfony\Component\Console\Application->getTerminalWidth()
#5 /vagrant/www/test.dev/laravel/vendor/laravel/framework/src/Illuminate/Console/Application.php(201): Symfony\Component\Console\Application->renderException(Object(ErrorException), Object(Symfony\Component\Console\Output\StreamOutput))
#6 /vagrant/www/test.dev/laravel/vendor/symfony/console/Symfony/Component/Console/Application.php(131): Illuminate\Console\Application->renderException(Object(ErrorException), Object(Symfony\Component\Console\Output\StreamOutput))
#7 /vagrant/www/test.dev/laravel/artisan(59): Symfony\Component\Console\Application->run()
#8 {main} [] []

Here is the code that is triggering these errors after 10 min: 这是在10分钟后触发这些错误的代码:

static::listen(
    'progress',
    function ($indicator = '.', $line = null, $id = 0) {
        $output = new \Symfony\Component\Console\Output\ConsoleOutput();

        $extra = [];

        if (static::$debug > 2) {
            if (!empty($line) && $line !== true)
                $extra[] = "line=$line";

            if (!empty($id)) {
                if (is_array($id))
                    $id = implode(',', $id);

                if (!empty($id))
                    $extra[] = "ID=$id";
            }
        }

        if (!empty($extra))
            $output->writeln('[' . implode(', ', $extra) . ']');
        elseif ($line === true)
            $output->writeln("\n$indicator");
        else
            $output->write($indicator);

        static $gc_count = 0;

        $gc_count++;

        if ($gc_count > 25) {
            $gc_count = 0;

            gc_collect_cycles();
        }
    },
    'event'
);

I've looked around for a solution to this so I added the gc_collect_cycles() line hoping that would help but it does not resolve the problem. 我一直在寻找解决方案,因此我添加了gc_collect_cycles()行希望对您有所帮助,但并不能解决问题。

Looking at the Symfony ConsoleOutput code it is always doing an fopen($outputStream, 'w') but I couldn't find anything where it does close it again. 查看Symfony ConsoleOutput代码,它始终在执行fopen($outputStream, 'w')但在重新关闭它的地方找不到任何东西。
So you could either try to close it yourself at the end of your function: 因此,您可以尝试在函数结束时自行关闭它:

$resource = $output->getStream();
fclose($resource);

Or only try to instantiate it once and reuse it then. 或者只尝试实例化一次,然后再使用。

NOTE: Actually I think the garbage collection should close it if there is no longer a reference to the anonymous function. 注意:实际上,我认为,如果不再有对匿名函数的引用,则垃圾收集应将其关闭。 Tough I don't know what the static::listen method is doing, so it may be worth a try to close it manually. 艰难的我不知道static::listen方法在做什么,所以值得手动关闭它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM