Giter Site home page Giter Site logo

process's Introduction

amphp/process

AMPHP is a collection of event-driven libraries for PHP designed with fibers and concurrency in mind. amphp/process provides an asynchronous process dispatcher that works on all major platforms (including Windows). It makes running child processes simple.

As Windows pipes are file handles and do not allow non-blocking access, this package makes use of a process wrapper, that provides access to these pipes via sockets. On Unix-like systems it uses the standard pipes, as these can be accessed without blocking there. Concurrency is managed by the Revolt event loop.

Latest Release MIT License

Installation

This package can be installed as a Composer dependency.

composer require amphp/process

The package requires PHP 8.1 or later.

Usage

Processes are started with Process::start():

<?php

require __DIR__ . "/vendor/autoload.php";

use Amp\ByteStream;
use Amp\Process\Process;

// "echo" is a shell internal command on Windows and doesn't work.
$command = DIRECTORY_SEPARATOR === "\\" ? "cmd /c echo Hello World!" : "echo 'Hello, world!'";

$process = Process::start($command);

Amp\async(fn () => Amp\ByteStream\pipe($process->getStdout(), ByteStream\getStdout()));
Amp\async(fn () => Amp\ByteStream\pipe($process->getStderr(), ByteStream\getStderr()));

$exitCode = $process->join();

echo "Process exited with {$exitCode}.\n";

Custom Working Directory

Processes are started with the working directory of the current process by default. The working directory can be customized to another directory if needed:

$process = Amp\Process\Process::start($command, workingDirectory: '/path/of/your/dreams');

Custom Environment Variables

Processes are started with the environment variables of the current process by default. The environment can be customized by passing an associative array mapping variables names to their values:

$process = Amp\Process\Process::start($command, environment: [
    'PATH' => '/usr/bin/local'
]);

Versioning

amphp/process follows the semver semantic versioning specification like all other amphp packages.

Security

If you discover any security related issues, please use the private security issue reporter instead of using the public issue tracker.

License

The MIT License (MIT). Please see LICENSE for more information.

process's People

Contributors

bilge avatar bwoebi avatar danog avatar daverandom avatar ekstazi avatar gemorroj avatar grachevko avatar haohetao avatar joshdifabio avatar kelunik avatar peter279k avatar rdlowrey avatar skedone avatar trowski avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

process's Issues

Recycle process

Starting and stopping processes is a very time consuming thing.

Would it be possible to leave a process open after the command finished and let it run another command? Or maybe some kind of process pooling to reduce start/stop overhead?

Not sure its possible at all...

How to start background processes

What is the recommended way to start and stop a process that shall run for some time in the background (windows and linux)? I was not able to find a stable solution so far.

(see https://github.com/pact-foundation/pact-php/blob/master/src/PhpPact/Standalone/Runner/ProcessRunner.php)

My current approach is

public function runNonBlocking(): void
{
  Loop::run(function () {
            yield $this->process->start();
            $this->process->getStdout()->read()->onResolve(function (\Throwable $reason = null, $value) {
                $this->output .= $value;
            });
            $this->process->getStderr()->read()->onResolve(function (\Throwable $reason = null, $value) {
                $this->output .= $value;
            });
            Loop::stop();
   };)
}
    public function stop(): bool
    {
        if (!$this->process->isRunning()) {
            return true;
        }
        $pid = $this->process->getPid();
        if ('\\' === \DIRECTORY_SEPARATOR) {
            \exec(\sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
            if ($exitCode) {
                throw new ProcessException(\sprintf('Unable to kill the process (%s).', \implode(' ', $output)));
            }
        }
        $this->process->kill(); // this is not reliable on windows
        if ($this->process->isRunning()) {
            throw new ProcessException(\sprintf('Error while killing process "%s".', $pid));
        }
        return true;
    }

Two connected errors:

Reason 1: https://ci.appveyor.com/project/mattermack/pact-php/builds/25020714
Reason 2: https://ci.appveyor.com/project/mattermack/pact-php/builds/25020861

'Could not start process' (0)

my process I try to start, errors while starting up.

I get errors like

Uncaught exception: 'Amp\Process\ProcessException' with message 'Could not start process' (0)
> in /cluster/www/www/www/rocket/vendor/amphp/process/lib/Internal/Posix/Runner.php:88
Stack trace:
#0 /cluster/www/www/www/rocket/vendor/amphp/process/lib/Process.php(96): Amp\Process\Internal\Posix\Runner->start('{ ('/usr/bin/ph...', '', Array, Array)
#1 /cluster/www/www/www/rocket/vendor/amphp/parallel/lib/Context/Process.php(166): Amp\Process\Process->start()
#2 /cluster/www/www/www/rocket/vendor/amphp/parallel/lib/Worker/AbstractWorker.php(59): Amp\Parallel\Context\Process->start()
#3 /cluster/www/www/www/rocket/vendor/amphp/parallel/lib/Worker/DefaultPool.php(137): Amp\Parallel\Worker\AbstractWorker->enqueue(Object(BlockingTask))
#4 /cluster/www/www/www/rocket/helpers/ImageHelper.php(73): Amp\Parallel\Worker\DefaultPool->enqueue(Object(BlockingTask))
#5 [internal function]: {closure}('a', NULL)
#6 /cluster/www/www/www/rocket/vendor/amphp/amp/lib/Coroutine.php(39): Generator->current()
#7 /cluster/www/www/www/rocket/vendor/amphp/amp/lib/Loop/Driver.php(119): Amp\Coroutine->__construct(Object(Generator))
#8 /cluster/www/www/www/rocket/vendor/amphp/amp/lib/Loop/Driver.php(70): Amp\Loop\Driver->tick()
#9 /cluster/www/www/www/rocket/vendor/amphp/amp/lib/Loop.php(76): Amp\Loop\Driver->run()
#10 /cluster/www/www/www/rocket/helpers/ImageHelper.php(80): Amp\Loop::run(Object(Closure))

I guess the problem itself is, that proc_open is on the disable_functions list and therefore php does not allow to start the process.

my calling code looks like

function resize_image($filename, $destinations = null, $allowEnlarge = false)
{
    $result = true;

    Amp\Loop::run(function () use ($filename, $destinations, $allowEnlarge, &$result) {
        $pool = new DefaultPool();

        $promises = array();
        foreach($destinations as $name => $params) {
            $promises[] = $pool->enqueue(new BlockingTask('resize_image_process', $filename, array($name => $params), $allowEnlarge));
        }

        foreach($promises as $promise) {
            $result = $result && yield $promise;
        }
        $result = $result && yield $pool->shutdown();
    });

    return $result;
}

while I am using classes from the examples from the parallel component
https://github.com/amphp/parallel/tree/master/examples

process immediate exit after sigterm

Some example code to reproduce

test.php

<?php
require __DIR__.'/vendor/autoload.php';

$onInterrupt = \Amp\Loop::onSignal(SIGINT, function ($reference){
	echo "sigterm\n";
	//\Amp\Loop::cancel($reference);
});
\Amp\Loop::run(function() use($onInterrupt ){
	$process = new \Amp\Process\Process("php test-process.php");
	$pid = yield $process->start();
	\Amp\ByteStream\pipe($process->getStdout(), \Amp\ByteStream\getStdout());
	\Amp\ByteStream\pipe($process->getStderr(), \Amp\ByteStream\getStderr());
	$code = yield $process->join();
	echo $code;
	if(file_exists("/proc/{$pid}")) {
		echo "Process still running\n";
	}
	yield new \Amp\Delayed(10000);
	\Amp\Loop::cancel($onInterrupt);
});

test-process.php

<?php
require __DIR__.'/vendor/autoload.php';

//pcntl_async_signals(true);
\Amp\Loop::onSignal(SIGINT, function (){
	echo "sigterm from parent\n";
});
echo "Start\n";
\Amp\Loop::repeat(100, function(){
	echo "test\n";
	sleep(1);
});
\Amp\Loop::run();
echo "exit\n";

Steps to reproduce

  1. I start script test.php. Example output was:
Start
test
test
test

Process list:

26434 pts/7    S+     0:00 php ./test.php
26435 pts/7    S+     0:00 sh -c { (php test-process.php) <&3 3<&- 3>/dev/null & } 3<&0;pid=$!; echo $pid >&3; wait $pid; RC=$?; echo $RC >&3; exit $RC
26436 pts/7    S+     0:00 php test-process.php
  1. I send sigint(ctrl+c) to script. Output was:
^C0Process still running
sigterm from parent
test
sigterm

Processs list:

27301 pts/7    S+     0:00 php ./test.php
27303 pts/7    S+     0:00 php test-process.php
  1. I wait for script to finish. Output was:
test
test
test
test
test
test
test
test
test
test

Actual behavior

As you can see when sigint received php closed process wrapper (sh -c) and send sigint to test-process.php. amp/Process wait for process wrapper to finish but doesn't wait for test-process.php. But pipes will continue to work after that. The child process only killed after main process exit.

Expected behavior

Process::join only resolves when test-process.php finished/halted/cancelled.

Moderate to high concurrency load causes "Failed to launch process" errors on Windows

Using Artax (composer require amphp/artax) and running the following code on Windows:

        Loop::run(function () {
            foreach (range(1, 1000) as $id) {
                $this->client->request('http://example.com')->onResolve(function ($error, $response) {
                    if ($error) {
                        echo "$error\n";

                        return;
                    }
                });
            }
        });

Generates the following error:

Amp\Process\ProcessException: Process did not connect to server before timeout elapsed in vendor\amphp\process\lib\Internal\Windows\SocketConnector.php:344

The key is to have a high concurrency limit (i.e. 1000 in this case). Lower limits can trigger trigger it, too, but they need to be at least in the region of ~500 on my Windows 7 system.

The error is strange because only a couple of seconds are passing, at most, before the errors start streaming in. The same code works (can successfully download a response) with lower concurrency limits (e.g. around 200 or so).


Edit: After further testing, I can trigger this with a limit as low as 50. It seems to depend on how long the destination server takes to respond. Loading larger pages is more likely to cause it to fail. Again, only a second or so of real user time is passing but even trying to load 50 heavy URLs at once will cause it to fail the majority of the time and there seems to be no way to override the timeout.

Proper support for Windows

While it works on Windows, it doesn't allow non-blocking I/O, because Windows pipes are file handles and do not allow non-blocking mode. We have to use something like https://github.com/cubiclesoft/createprocess-windows to launch the processes to allow non-blocking stream reads / writes. This is required for amphp/parallel to work on Windows. As long as this isn't fixed, we have to use the BlockingDriver on Windows for amphp/file.

See comment on amphp/file@edc6c09.

Zombie Processes

I was experimenting with the new beta [v2.0.0-beta.3] version and I identified that zombies processes are left behind when the process exits or when it is being killed using the $process->kill() method. Is this something that will be fixed in future releases?

v2 not working on FPM while v1 does

Hi, testing Parallel v2 with fibers on php 8.1 FPM with a simple task service, but it cannot work anymore because the underlaying Process requires pcntl which is not available on FPM.
The same code with Promises works on Parallel/Process v1

SocketConnector fails to close sockets on PHP8/Win

This code is prone to throwing TypeErrors in PHP 8.0.3/Windows:

Fatal error: Uncaught TypeError: fclose(): supplied resource is not a valid stream resource in amphp\process\lib\Internal\Windows\SocketConnector.php:313
Stack trace:
#0 amphp\process\lib\Internal\Windows\SocketConnector.php(313): fclose(Resource id #176)
#1 amphp\amp\lib\Loop\NativeDriver.php(321): Amp\Process\Internal\Windows\SocketConnector->onReadableExitCode('t', Resource id #176, Object(Amp\Process\Internal\Windows\Handle))
#2 amphp\amp\lib\Loop\NativeDriver.php(127): Amp\Loop\NativeDriver->selectStreams(Array, Array, 4.963)

Amphp gets stuck in and infinite loop doing nothing if firewall delays port access

@kelunik told me to open a ticket here.

Please open an issue at https://github.com/amphp/parallel for the infinite loop and https://github.com/amphp/process for the ports if you want.

its quite a while but as the problem with box was easy solvable by using the --no-parallel option i simply forgot until i hit the problem again with fink.

i am not sure where to write which info, it feels i would post the same text in parallel and process as i haven't used amphp directly but only tools which use it, i don't know the internals.

if i run fink it simply gets stuck forever on a windows system with a firewall.

php fink.phar https://getcomposer.org

console

if my firewall is in learning mode, it ask me to allow ampXXXX.tmp a local connection.

firewall-dialog

after allowing it, the connection monitor show the following:

connections

this 3 php and amp processes stay there forever in an infinite loop and are doing nothing (no more as the initial 22 bytes are sent or received).

if i run the firewall in allow all mode (which sadly makes no sense at all), it works without a problem.

so it looks like amphp has a problem if the port is not instantly accessible but delayed by a firewall learning mode dialog.
as the amp process names are randomly generated it is not possible to precreate the firewall rules.
having some kind of check if ports can be accessed and if not some kind of fallback could be a solution. a slow synchronous processing is still faster as a infinite do nothing processing :)
edit: non-dynamic ports can also help (only in combination with non random process names)

ProcessException with message 'Could not determine PID'

The following code:

\Amp\Loop::run(function() {
    $process = new \Amp\Process\Process('diff <(echo 1) <(echo 2)');
    yield $process->start();
    yield $process->join();
});

Raises exception:

Amp\Process\ProcessException: Could not determine PID

vendor/amphp/process/lib/Internal/Posix/Runner.php:54
vendor/amphp/amp/lib/Loop/NativeDriver.php:201
vendor/amphp/amp/lib/Loop/NativeDriver.php:104
vendor/amphp/amp/lib/Loop/Driver.php:138
vendor/amphp/amp/lib/Loop/Driver.php:72
vendor/amphp/amp/lib/Loop.php:95
tests/CsvDiffIteratorTest.php:69

Actual command executed is:
{ (diff <(echo 1) <(echo 2)) <&3 3<&- 3>/dev/null & } 3<&0; trap "" INT TERM QUIT HUP;pid=$!; echo $pid >&3; wait $pid; RC=$?; echo $RC >&3; exit $RC

Executing it in terminal gives:

$ { (diff <(echo 1) <(echo 2)) <&3 3<&- 3>/dev/null & } 3<&0; trap "" INT TERM QUIT HUP;pid=$!; echo $pid >&3; wait $pid; RC=$?; echo $RC >&3
[1] 172
bash: 3: Bad file descriptor
1c1
< 1
---
> 2
[1]+  Exit 1                  ( diff <(echo 1) <(echo 2) ) 0<&3 3>&- 3> /dev/null
bash: 3: Bad file descriptor

Ability to restart process

Please add ability to restart process:

$process = new Process('ls -a');
yield $process->start();
yield $process->join();
yield $process->start();

or

$process = new Process('ls -a');
yield $process->start();
yield $process->restart();

Add debug info

Process should have a __debugInfo, because otherwise a var_dump is really, really long.

Application stucks when launch application that requires elevated privileges on Windows

The following code:

Loop::run(static function () {

    $process = new Process("diskpart");
    yield $process->start();

});

Problem: app just stucks and does not stdout anything, using a timeout completely breaks the script execution:

Loop::run(static function () {

    $process = new Process("diskpart");

    yield timeout($process->start(), 5000);

});

Here an exception:

PHP Fatal error:  Uncaught Exception: stream_select(): supplied resource is not a valid stream resource in C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amphp\amp\lib\Loop\NativeDriver.php:79
Stack trace:
#0 [internal function]: Amp\Loop\NativeDriver->Amp\Loop\{closure}(2, 'stream_select()...', 'C:\\Users\\Admin\\...', 294, Array)
#1 C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amphp\amp\lib\Loop\NativeDriver.php(294): stream_select(Array, Array, NULL, 4, 0)
#2 C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amphp\amp\lib\Loop\NativeDriver.php(127): Amp\Loop\NativeDriver->selectStreams(Array, Array, 4)
#3 C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amphp\amp\lib\Loop\Driver.php(138): Amp\Loop\NativeDriver->dispatch(true)
#4 C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amphp\amp\lib\Loop\Driver.php(72): Amp\Loop\Driver->tick()
#5 C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amp in C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amphp\amp\lib\Loop\NativeDriver.php on line 79

Process finished with exit code 255

I found a possible solution to solve this problem, but I'm not good at creating PR.

By adding the following code to "lib/Internal/Windows/SocketConnector.php" at the end of the function "onProcessConnectTimeout" (I added after the line 367)

if ($handle->status === ProcessStatus::STARTING) {
    Loop::cancel($handle->childPidWatcher);
    $handle->pidDeferred->fail($error);
}

The problem is solved completely and now the output when running the first script:

PHP Fatal error:  Uncaught Amp\Process\ProcessException: Failed to create child process: 740: Запрошенная операция требует повышения. in C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amphp\process\lib\Internal\Windows\SocketConnector.php:359
Stack trace:
#0 C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amphp\amp\lib\Loop\NativeDriver.php(142): Amp\Process\Internal\Windows\SocketConnector->onProcessConnectTimeout('e', Object(Amp\Process\Internal\Windows\Handle))
#1 C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amphp\amp\lib\Loop\Driver.php(138): Amp\Loop\NativeDriver->dispatch(true)
#2 C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amphp\amp\lib\Loop\Driver.php(72): Amp\Loop\Driver->tick()
#3 C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amphp\amp\lib\Loop.php(95): Amp\Loop\Driver->run()
#4 C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\test.php(17): Amp\ in C:\Users\Admin\Documents\win_install_stuff\windows_installer_v0\vendor\amphp\process\lib\Internal\Windows\SocketConnector.php on line 359

Process finished with exit code 255

PS. Sorry for a little machine translation, English is not my first language

Doesn't work with dg/bypass-finals

Create this bootstrap code and use it in phpunit, then rerun the tests in this project:

<?php

declare(strict_types=1);

require_once __DIR__ . '/../vendor/autoload.php';

\DG\BypassFinals::enable();

This results in

EEEEEEEEEEE.EEEEEEEEEEEEEEEEEEEEEEEESFE                           39 / 39 (100%)

Time: 00:00.036, Memory: 10.00 MB

There were 36 errors:

1) Amp\Process\Test\ProcessTest::testIsRunning
Amp\Process\ProcessException: Process could not be started: Errno: 2; fseek(): Stream does not support seeking
...

In case there isn't anything that can be done about the compatibility, can you at least throw the useful message when its presence is detected? Because finding the culprit isn't easy in large project.

not get response of a user define method

how i get response of my index method for further use?

<?php

namespace console\controllers;

use Yii;
#use Amp\Promise;
#use Amp\ByteStream;
use Amp\Process\Process;

class TestController extends \yii\console\Controller
{
	public function actionTest(){

		// php yii test/test
		\Amp\Loop::run(function () {

				for ($i=0; $i <10 ; $i++) { 
					 $commands[] = $this->index($i);
				}
			    $promises = [];
			    foreach ($commands as $command) {
			        $process = new Process($command);
			        $promises[] = new \Amp\Coroutine($this->show_process_output($process));
			    }
			// print_r($promises);
		    // yield all($promises);
		});
	}

	public function index($i){
        // echo $i." =>  hello word"."\n";
        return $i;
	}


	function show_process_output(Process $process): \Generator
	{
	    yield $process->start();

	    $stream = $process->getStdout();

	    while (null !== $chunk = yield $stream->read()) {
	        // echo $chunk;
	    }

	    $code = yield $process->join();
	    $pid = $process->getPid();
	    // echo "Process {$pid} exited with {$code}\n";
	}
}

php8 on windows with error

D:\sites\git\epmms2-award>vendor\bin\grumphp.bat run
GrumPHP is sniffing your code!
Running tasks with priority 0!
==============================

Running task 1/5: phpcs...
Running task 2/5: phpcsfixer...
Running task 3/5: shell... ✘
Running task 4/5: composer...
Running task 5/5: yamllint... ✔
Aborted ...
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▄▄▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▄
▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
▄███▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
▐█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
▀█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
▀▀▓▓▓▓▓▓▓▓▓▓▓▓█▀▀▀▀▀▀▀▀▀▀▀▀▀▀████████████▄
▄███████ ██████████
███████▀ ▀▀▀▀▀▄ ▄▀▀▀▀▀ █████ ▀
▐████ ▐██ ▐██ ████▌
████▌ ███
▌██▌ ▄▄ ▄▄ ▐███
███ ▄▄▄▄▄▄▄▄▄▄▄▄ ▐███
██▄ ▐███████████████████████████
█▀███████████▀ ▀▀███████████
██████████▄███████▄███████████
▐█████████████████████████████
█████████████████████████████
██ █████████████████████▐██▀
▀ ▐███████████████████▌ ▐▀
████▀████████▀▐███
▀█▌ ▐█████ ██▌
██▀ ▐▀

   ██████████████████████████████████
   █░░░░░░▀█▀░░░░░░▀█░░░░░░▀█▀░░░░░▀█
   █░░▐█▌░░█░░░██░░░█░░██░░░█░░░██░░█
   █░░▐█▌░░█░░░██░░░█░░██░░░█░░░██░░█
   █░░▐█▌░░█░░░██░░░█░░░░░░▄█░░▄▄▄▄▄█
   █░░▐█▌░░█░░░██░░░█░░░░████░░░░░░░█
   █░░░█░░░█▄░░░░░░▄█░░░░████▄░░░░░▄█
   ██████████████████████████████████

shell

The executable for "sh" could not be found.
To skip commit checks, add -n or --no-verify flag to commit command
PHP Fatal error: Uncaught TypeError: fclose(): supplied resource is not a valid stream resource in D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php:221
Stack trace:
#0 D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php(221): fclose(Resource id #530)
amphp/amp#1 D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php(201): Amp\Process\Internal\Windows\Runner->free(Object(Amp\Process\Internal\Windows\Handle))
amphp/amp#2 D:\sites\git\epmms2-award\vendor\amphp\process\lib\Process.php(85): Amp\Process\Internal\Windows\Runner->destroy(Object(Amp\Process\Internal\Windows\Handle))
amphp/amp#3 [internal function]: Amp\Process\Process->__destruct()
amphp/amp#4 {main}
thrown in D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php on line 221

Fatal error: Uncaught TypeError: fclose(): supplied resource is not a valid stream resource in D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php:221
Stack trace:
#0 D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php(221): fclose(Resource id #530)
amphp/amp#1 D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php(201): Amp\Process\Internal\Windows\Runner->free(Object(Amp\Process\Internal\Windows\Handle))
amphp/amp#2 D:\sites\git\epmms2-award\vendor\amphp\process\lib\Process.php(85): Amp\Process\Internal\Windows\Runner->destroy(Object(Amp\Process\Internal\Windows\Handle))
amphp/amp#3 [internal function]: Amp\Process\Process->__destruct()
amphp/amp#4 {main}
thrown in D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php on line 221

Not running at windows

I try to run the tests at windows 10 with virtualbox. What do I need to do to fix these errors?

php -v
PHP 7.3.6 (cli) (built: May 29 2019 12:11:00) ( ZTS MSVC15 (Visual C++ 2017) x64 )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.6, Copyright (c) 1998-2018 Zend Technologies
.\vendor\bin\phpunit
PHPUnit 6.5.14 by Sebastian Bergmann and contributors.

....S.......................................FEF                   47 / 47 (100%)

Time: 1.23 minutes, Memory: 6.00MB

There was 1 error:

1) Amp\Process\Test\ProcessTest::testSignal
Error: Undefined constant 'SIGTERM'

F:\windows\process\test\ProcessTest.php:384
F:\windows\process\vendor\amphp\amp\lib\Coroutine.php:76
F:\windows\process\vendor\amphp\amp\lib\Internal\Placeholder.php:130
F:\windows\process\vendor\amphp\amp\lib\Delayed.php:22
F:\windows\process\vendor\amphp\amp\lib\Loop\NativeDriver.php:130
F:\windows\process\vendor\amphp\amp\lib\Loop\Driver.php:134
F:\windows\process\vendor\amphp\amp\lib\Loop\Driver.php:72
F:\windows\process\vendor\amphp\amp\lib\Loop.php:84
F:\windows\process\test\ProcessTest.php:386

--

There were 2 failures:

1) Amp\Process\Test\ProcessTest::testKillPHPImmediatly
Failed asserting that a string is empty.

F:\windows\process\test\ProcessTest.php:374
F:\windows\process\vendor\amphp\amp\lib\Coroutine.php:76
F:\windows\process\vendor\amphp\amp\lib\Internal\Placeholder.php:130
F:\windows\process\vendor\amphp\amp\lib\Coroutine.php:81
F:\windows\process\vendor\amphp\amp\lib\Internal\Placeholder.php:130
F:\windows\process\vendor\amphp\amp\lib\Deferred.php:45
F:\windows\process\lib\Internal\Windows\SocketConnector.php:270
F:\windows\process\vendor\amphp\amp\lib\Loop\NativeDriver.php:206
F:\windows\process\vendor\amphp\amp\lib\Loop\NativeDriver.php:97
F:\windows\process\vendor\amphp\amp\lib\Loop\Driver.php:134
F:\windows\process\vendor\amphp\amp\lib\Loop\Driver.php:72
F:\windows\process\vendor\amphp\amp\lib\Loop.php:84
F:\windows\process\test\ProcessTest.php:375

2) Amp\Process\Test\ProcessTest::testDebugInfo
Failed asserting that Array &0 (
    'command' => '"php" "F:\windows\process\test/bin/worker.php"'
    'cwd' => 'F:\windows\process\test'
    'env' => Array &1 ()
    'options' => Array &2 ()
    'pid' => null
    'status' => -1
) is identical to Array &0 (
    'command' => ''php' 'F:\windows\process\test/bin/worker.php''
    'cwd' => 'F:\windows\process\test'
    'env' => Array &1 ()
    'options' => Array &2 ()
    'pid' => null
    'status' => -1
).

F:\windows\process\test\ProcessTest.php:401
F:\windows\process\vendor\amphp\amp\lib\Coroutine.php:41
F:\windows\process\vendor\amphp\amp\lib\Loop\Driver.php:123
F:\windows\process\vendor\amphp\amp\lib\Loop\Driver.php:72
F:\windows\process\vendor\amphp\amp\lib\Loop.php:84
F:\windows\process\test\ProcessTest.php:409

ERRORS!
Tests: 47, Assertions: 64, Errors: 1, Failures: 2, Skipped: 1.

Undefined property: Amp\Process::$proc

When running a sub-process within Amp using Process, I sometimes see these notices output in logs:

Undefined property: Amp\Process::$proc in /var/www/vendor/amphp/process/Process.php on line 178

and:

[2017-02-15 06:41:41] notice Undefined property: Amp\Process::$proc in /var/www/vendor/amphp/process/Process.php on line 224

These seem to be from $this->proc in the cancel() and pid() methods.

I understand that notices are mostly harmless, but is there some way this code could be rewritten to avoid giving notices?

Process getting stuck because of a full STDOUT/STDERR pipe

This is not a bug, only a little help that might be useful for some people passing through here.

It might be worth noting a scenario I've just encountered: I'm running a ffmpeg command with amphp/process and I was only interested in what was produced by STDOUT (wav audio).

So basically it was as simple as:

$command = sprintf('ffmpeg -i %s -f wav -ac 1 -c:a pcm_s16le -ar 16000 pipe:1', escapeshellarg($filePath));
$process = Process::start($command);
while (($chunk = $process->getStdout()->read()) !== null) {
    // ... do stuff
}
$process->join();

But I noticed that for some reason, the process got eventually stuck on the read() and could go no further.
After digging for a while, and remembering a similar situation using the native proc_open() with $pipes, I understood that it was not because I didn't care about STDERR in my case, that the corresponding pipe was not filling up anyway! Until it was completely full and the process got stuck, waiting for the pipe to be read/emptied.

In this precise case, the optimal solution is not to fill STDERR in the first place, using the options -hide_banner -loglevel quiet for ffmpeg, but if you cannot control the command's output, I suppose you can use this:

async(
    ByteStream\pipe(...),
    $process->getStderr(),
    new WritableResourceStream(\fopen('/dev/null', 'wb'))
)->ignore();

Feel free to correct me. I did not test this solution myself but I thought it was important to mention.

Catching STDERR output

I'm not sure if y'all take support requests directly through the issue queue, so I'll try my luck. I created the tool Drall and one of it's main features is parallel processing, which is powered by amphp/process.

Reference: context.

Question 1: Catch STDERR

$sOutput = yield ByteStream\buffer($process->getStdout());

Here, I only get the STDOUT contents from $process. How do I get both STDOUT and STDERR, preferably, intermingled output, i.e. not in separate variables. Is appending 2>&1 the only way? Or is there another way?

Question 2: No buffer

Currently, I use ByteStream\buffer($process->getStdout()); where I catch the output in a variable. Is there a way to let the output go to STDOUT directly instead of catching it in a variable?

Any help will be appreciated.

php8 on windows with error

D:\sites\git\epmms2-award>vendor\bin\grumphp.bat run
GrumPHP is sniffing your code!
Running tasks with priority 0!
==============================

Running task 1/5: phpcs...
Running task 2/5: phpcsfixer...
Running task 3/5: shell... ✘
Running task 4/5: composer...
Running task 5/5: yamllint... ✔
Aborted ...
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▄▄▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▄
▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
▐▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
▄███▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
▐█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
▀█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▌
▀▀▓▓▓▓▓▓▓▓▓▓▓▓█▀▀▀▀▀▀▀▀▀▀▀▀▀▀████████████▄
▄███████ ██████████
███████▀ ▀▀▀▀▀▄ ▄▀▀▀▀▀ █████ ▀
▐████ ▐██ ▐██ ████▌
████▌ ███
▌██▌ ▄▄ ▄▄ ▐███
███ ▄▄▄▄▄▄▄▄▄▄▄▄ ▐███
██▄ ▐███████████████████████████
█▀███████████▀ ▀▀███████████
██████████▄███████▄███████████
▐█████████████████████████████
█████████████████████████████
██ █████████████████████▐██▀
▀ ▐███████████████████▌ ▐▀
████▀████████▀▐███
▀█▌ ▐█████ ██▌
██▀ ▐▀

   ██████████████████████████████████
   █░░░░░░▀█▀░░░░░░▀█░░░░░░▀█▀░░░░░▀█
   █░░▐█▌░░█░░░██░░░█░░██░░░█░░░██░░█
   █░░▐█▌░░█░░░██░░░█░░██░░░█░░░██░░█
   █░░▐█▌░░█░░░██░░░█░░░░░░▄█░░▄▄▄▄▄█
   █░░▐█▌░░█░░░██░░░█░░░░████░░░░░░░█
   █░░░█░░░█▄░░░░░░▄█░░░░████▄░░░░░▄█
   ██████████████████████████████████

shell

The executable for "sh" could not be found.
To skip commit checks, add -n or --no-verify flag to commit command
PHP Fatal error: Uncaught TypeError: fclose(): supplied resource is not a valid stream resource in D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php:221
Stack trace:
#0 D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php(221): fclose(Resource id #530)
#1 D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php(201): Amp\Process\Internal\Windows\Runner->free(Object(Amp\Process\Internal\Windows\Handle))
#2 D:\sites\git\epmms2-award\vendor\amphp\process\lib\Process.php(85): Amp\Process\Internal\Windows\Runner->destroy(Object(Amp\Process\Internal\Windows\Handle))
#3 [internal function]: Amp\Process\Process->__destruct()
#4 {main}
thrown in D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php on line 221

Fatal error: Uncaught TypeError: fclose(): supplied resource is not a valid stream resource in D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php:221
Stack trace:
#0 D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php(221): fclose(Resource id #530)
#1 D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php(201): Amp\Process\Internal\Windows\Runner->free(Object(Amp\Process\Internal\Windows\Handle))
#2 D:\sites\git\epmms2-award\vendor\amphp\process\lib\Process.php(85): Amp\Process\Internal\Windows\Runner->destroy(Object(Amp\Process\Internal\Windows\Handle))
#3 [internal function]: Amp\Process\Process->__destruct()
#4 {main}
thrown in D:\sites\git\epmms2-award\vendor\amphp\process\lib\Internal\Windows\Runner.php on line 221

amphp/process kills sub process on exit

wrapper.php

<?php
echo 'foo';
sleep(1);
touch('a');

Following works as expected, outputs foo, exits immediately and after 1 second creates file 'a'.

<?php

$fd = [
    ["pipe", "r"], // stdin
    ["pipe", "w"], // stdout
];
$handle = @\proc_open('php wrapper.php', $fd, $pipes);

echo fread($pipes[1], 100);

Following does not work as expected. Outputs foo, exits immediately but file is not created.

<?php
require_once "vendor/autoload.php";
\Amp\Loop::run(function () {
    $process = new \Amp\Process\Process("php wrapper.php");
    yield $process->start();
    echo yield $process->getStdout()->read();
});

amphp/process 1.x on Windows: Trying to start a non-existent executable gets stuck forever

Hi, I couldn't find information anywhere whether the 1.x branch is still maintained. If it isn't, my apologies for bothering you.

I found that trying to start a non-existent executable using amphp/process 1.x gets stuck forever on Windows. Minimal example:

<?php

require "vendor/autoload.php";

use Amp\Process\Process;
use function Amp\Promise\wait;

$process = new Process("asdfasdf");
$pid = wait($process->start());

This seems to be a very similar problem to #51, and the patch proposed there (Nicodinus@3d41ea5) fixes it for me.

posix/Runner::kill not worked

some example code:

$process = yield Amp\Parallel\Context::run('test.php');
$process->kill();

test.php:

sleep(30);

As i can see on linux systems(ps -aux | grep php) test,php keep runned and detached after end of main script.

This happen because kill only terminate sh but keep php detached.

Killing detached process

Actually killing a process which is detached does not work

$process = new \Amp\Process\Process("setsid sleep 100");
$process->start();

$pid = yield $process->getPid();

$process->kill();

Then doing a ps aufx|grep sleep show the process still running, it is possible to kill him since we have the correct id and we can use then posix_kill, but should we do that (it introduce maybe a new extension dependency)

Exception "ProcessException: Received 0 of 5 expected bytes" when reading from stdout out of time

I've been experimenting with Amp\Process to better understand how it works. I launched several processes, connecting them stdout -> stdin, simulated various situations in order to understand where errors could occur and how to handle them correctly, including so that there were no zombie processes left. I have encountered one problem, the nature of which is not clear to me.

Important: I am using the Windows 10 operating system and what I am working on will run on the same operating system.

I will give some synthetic examples. Most of them work correctly, but one works unexpectedly. In all examples, I will use the ImageMagick command to convert a PNG image to a JPEG.

Example 1 (works well):

\Amp\Process\Process::start([
  'magick',
  'image.png', // input file
  '-quality', '100',
  'JPEG:image.jpg' // output file
]);

\Revolt\EventLoop::run();

Now I modify this example to pass the input image to stdin.

Example 2 (works well):

$content = \file_get_contents('image.png');

$process = \Amp\Process\Process::start([
  'magick',
  '-', // input stdin
  '-quality', '100',
  'JPEG:image.jpg' // output file
]);

$process->getStdin()->write($content);
$process->getStdin()->end();

\Revolt\EventLoop::run();

Next, I change the example so that the output image is sent to stdout.

Example 3 (works well):

$content = \file_get_contents('image.png');

$process = \Amp\Process\Process::start([
  'magick',
  '-', // input stdin
  '-quality', '100',
  'JPEG:-' // output stdout
]);

$process->getStdin()->write($content);
$process->getStdin()->end();

$content = \Amp\ByteStream\buffer($process->getStdout());
\file_put_contents('image.jpg', $content);

\Revolt\EventLoop::run();

Now I remove the code that reads from stdout. I expect the script to hang forever on the \Revolt\EventLoop::run(); call. I realize this is stupid code, but it demonstrates the problem.

Example 4 (not working correctly):

$content = \file_get_contents('image.png');

$process = \Amp\Process\Process::start([
  'magick',
  '-', // input stdin
  '-quality', '100',
  'JPEG:-' // output stdout
]);

$process->getStdin()->write($content);
$process->getStdin()->end();

\Revolt\EventLoop::run();

The script does hang at the line \Revolt\EventLoop::run();, but every time after exactly 120 seconds, I get an exception:

Uncaught Amp\Process\ProcessException: Received 0 of 5 expected bytes in C:\test\vendor\amphp\process\src\Internal\Windows\SocketConnector.php:245

The exception text is always identical, it reports the expected 5 bytes.

Then I additionally remove the code that sends the input image to stdin.

Example 5 (works well):

\Amp\Process\Process::start([
  'magick',
  '-', // input stdin
  '-quality', '100',
  'JPEG:-' // output stdout
]);

\Revolt\EventLoop::run();

In this case, the script hangs indefinitely, as expected (perhaps not indefinitely, but certainly much longer than 120 seconds).

Then I try again to specify the input file as the command argument.

Example 6 (works well):

\Amp\Process\Process::start([
  'magick',
  'image.png', // input file
  '-quality', '100',
  'JPEG:-' // output stdout
]);

\Revolt\EventLoop::run();

In this example, the script still hangs forever, as expected.

In each of the examples I tried replacing \Revolt\EventLoop::run(); with $process->join();, this did not affect the results in any way.

Below I provide the full stack trace of the exception from example 4, but with $process->join();:

PHP Fatal error:  Uncaught Amp\Process\ProcessException: Received 0 of 5 expected bytes in C:\test\vendor\amphp\process\src\Internal\Windows\SocketConnector.php:245
Stack trace:
#0 C:\test\vendor\amphp\process\src\Internal\Windows\SocketConnector.php(219): Amp\Process\Internal\Windows\SocketConnector->read(Object(Amp\ByteStream\ReadableResourceStream), 5)
#1 C:\test\vendor\amphp\process\src\Internal\Windows\SocketConnector.php(102): Amp\Process\Internal\Windows\SocketConnector->readExitCode(Object(Amp\ByteStream\ReadableResourceStream))
#2 C:\test\vendor\amphp\amp\src\functions.php(34): Amp\Process\Internal\Windows\SocketConnector->Amp\Process\Internal\Windows\{closure}()
#3 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(425): Amp\{closure}(NULL, NULL, Array)
#4 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(616): Revolt\EventLoop\Internal\AbstractDriver->invokeMicrotasks()
#5 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal\{closure}()
#6 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\DriverSuspension.php(64): Fiber->resume(NULL)
#7 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(425): Revolt\EventLoop\Internal\DriverSuspension::Revolt\EventLoop\Internal\{closure}()
#8 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(616): Revolt\EventLoop\Internal\AbstractDriver->invokeMicrotasks()
#9 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal\{closure}()
#10 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(498): Fiber->start()
#11 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(553): Revolt\EventLoop\Internal\AbstractDriver->invokeCallbacks()
#12 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal\{closure}()
#13 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(94): Fiber->resume()
#14 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\DriverSuspension.php(117): Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal\{closure}()
#15 C:\test\vendor\amphp\amp\src\Future.php(251): Revolt\EventLoop\Internal\DriverSuspension->suspend()
#16 C:\test\vendor\amphp\process\src\Internal\Windows\WindowsRunner.php(128): Amp\Future->await(NULL)
#17 C:\test\vendor\amphp\process\src\Process.php(123): Amp\Process\Internal\Windows\WindowsRunner->join(Object(Amp\Process\Internal\Windows\WindowsHandle), NULL)
#18 C:\test\test.php(19): Amp\Process\Process->join()
#19 {main}

Next Amp\Future\UnhandledFutureError: Unhandled future: Amp\Process\ProcessException: "Received 0 of 5 expected bytes"; Await the Future with Future::await() before the future is destroyed or use Future::ignore() to suppress this exception. The future has been created at #0 C:\test\vendor\amphp\amp\src\functions.php:40 Amp\Internal\FutureState->__construct()
#1 C:\test\vendor\amphp\process\src\Internal\Windows\SocketConnector.php:100 Amp\async()
#2 C:\test\vendor\amphp\process\src\Internal\Windows\WindowsRunner.php:101 Amp\Process\Internal\Windows\SocketConnector->connectPipes()
#3 C:\test\vendor\amphp\process\src\Process.php:80 Amp\Process\Internal\Windows\WindowsRunner->start()
#4 C:\test\test.php:9 Amp\Process\Process::start() in C:\test\vendor\amphp\amp\src\Internal\FutureState.php:53
Stack trace:
#0 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(425): Amp\Internal\FutureState->__destruct()
#1 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(616): Revolt\EventLoop\Internal\AbstractDriver->invokeMicrotasks()
#2 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal\{closure}()
#3 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\DriverSuspension.php(64): Fiber->resume(NULL)
#4 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(425): Revolt\EventLoop\Internal\DriverSuspension::Revolt\EventLoop\Internal\{closure}()
#5 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(616): Revolt\EventLoop\Internal\AbstractDriver->invokeMicrotasks()
#6 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal\{closure}()
#7 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(498): Fiber->start()
#8 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(553): Revolt\EventLoop\Internal\AbstractDriver->invokeCallbacks()
#9 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal\{closure}()
#10 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(94): Fiber->resume()
#11 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\DriverSuspension.php(117): Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal\{closure}()
#12 C:\test\vendor\amphp\amp\src\Future.php(251): Revolt\EventLoop\Internal\DriverSuspension->suspend()
#13 C:\test\vendor\amphp\process\src\Internal\Windows\WindowsRunner.php(128): Amp\Future->await(NULL)
#14 C:\test\vendor\amphp\process\src\Process.php(123): Amp\Process\Internal\Windows\WindowsRunner->join(Object(Amp\Process\Internal\Windows\WindowsHandle), NULL)
#15 C:\test\test.php(19): Amp\Process\Process->join()
#16 {main}

Next Revolt\EventLoop\UncaughtThrowable: Uncaught Amp\Future\UnhandledFutureError thrown in event loop callback Amp\Internal\FutureState::Amp\Internal\{closure} defined in C:\test\vendor\amphp\amp\src\Internal\FutureState.php:54; use Revolt\EventLoop::setErrorHandler() to gracefully handle such exceptions: Unhandled future: Amp\Process\ProcessException: "Received 0 of 5 expected bytes"; Await the Future with Future::await() before the future is destroyed or use Future::ignore() to suppress this exception. The future has been created at #0 C:\test\vendor\amphp\amp\src\functions.php:40 Amp\Internal\FutureState->__construct()
#1 C:\test\vendor\amphp\process\src\Internal\Windows\SocketConnector.php:100 Amp\async()
#2 C:\test\vendor\amphp\process\src\Internal\Windows\WindowsRunner.php:101 Amp\Process\Internal\Windows\SocketConnector->connectPipes()
#3 C:\test\vendor\amphp\process\src\Process.php:80 Amp\Process\Internal\Windows\WindowsRunner->start()
#4 C:\test\test.php:9 Amp\Process\Process::start() in C:\test\vendor\revolt\event-loop\src\EventLoop\UncaughtThrowable.php:13
Stack trace:
#0 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\AbstractDriver.php(400): Revolt\EventLoop\UncaughtThrowable::throwingCallback(Object(Closure), Object(Amp\Future\UnhandledFutureError))
#1 C:\test\vendor\revolt\event-loop\src\EventLoop\Internal\DriverSuspension.php(127): Revolt\EventLoop\Internal\AbstractDriver::Revolt\EventLoop\Internal\{closure}()
#2 C:\test\vendor\amphp\amp\src\Future.php(251): Revolt\EventLoop\Internal\DriverSuspension->suspend()
#3 C:\test\vendor\amphp\process\src\Internal\Windows\WindowsRunner.php(128): Amp\Future->await(NULL)
#4 C:\test\vendor\amphp\process\src\Process.php(123): Amp\Process\Internal\Windows\WindowsRunner->join(Object(Amp\Process\Internal\Windows\WindowsHandle), NULL)
#5 C:\test\test.php(19): Amp\Process\Process->join()
#6 {main}
  thrown in C:\test\vendor\revolt\event-loop\src\EventLoop\UncaughtThrowable.php on line 13

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.