2017-12-10 22:37:33 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Amp\Parallel\Context\Internal;
|
|
|
|
|
2018-10-11 01:31:34 +02:00
|
|
|
use Amp\Parallel\Context\Process;
|
2017-12-10 22:37:33 +01:00
|
|
|
use Amp\Parallel\Sync;
|
2019-01-04 23:58:05 +01:00
|
|
|
use Amp\Promise;
|
2017-12-10 22:37:33 +01:00
|
|
|
use function Amp\call;
|
|
|
|
|
|
|
|
// Doesn't exist in phpdbg...
|
|
|
|
if (\function_exists("cli_set_process_title")) {
|
|
|
|
@\cli_set_process_title("amp-process");
|
|
|
|
}
|
|
|
|
|
|
|
|
(function () {
|
|
|
|
$paths = [
|
|
|
|
\dirname(__DIR__, 5) . "/autoload.php",
|
|
|
|
\dirname(__DIR__, 3) . "/vendor/autoload.php",
|
|
|
|
];
|
|
|
|
|
|
|
|
foreach ($paths as $path) {
|
|
|
|
if (\file_exists($path)) {
|
|
|
|
$autoloadPath = $path;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isset($autoloadPath)) {
|
2018-10-25 05:35:27 +02:00
|
|
|
\trigger_error("Could not locate autoload.php in any of the following files: " . \implode(", ", $paths), E_USER_ERROR);
|
2017-12-10 22:37:33 +01:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
require $autoloadPath;
|
|
|
|
})();
|
|
|
|
|
2019-01-04 23:58:05 +01:00
|
|
|
(function () use ($argc, $argv) {
|
2017-12-10 22:37:33 +01:00
|
|
|
// Remove this scripts path from process arguments.
|
|
|
|
--$argc;
|
|
|
|
\array_shift($argv);
|
|
|
|
|
2018-10-06 17:05:49 +02:00
|
|
|
if (!isset($argv[0])) {
|
|
|
|
throw new \Error("No socket path provided");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove socket path from process arguments.
|
|
|
|
--$argc;
|
|
|
|
$uri = \array_shift($argv);
|
|
|
|
|
2018-10-12 01:11:02 +02:00
|
|
|
$key = "";
|
|
|
|
|
2018-10-11 01:31:34 +02:00
|
|
|
// Read random key from STDIN and send back to parent over IPC socket to authenticate.
|
2018-10-12 01:11:02 +02:00
|
|
|
do {
|
2018-10-24 04:26:26 +02:00
|
|
|
if (($chunk = \fread(\STDIN, Process::KEY_LENGTH)) === false || \feof(\STDIN)) {
|
2018-10-25 05:35:27 +02:00
|
|
|
\trigger_error("Could not read key from parent", E_USER_ERROR);
|
2018-10-21 17:03:26 +02:00
|
|
|
exit(1);
|
2018-10-12 01:11:02 +02:00
|
|
|
}
|
|
|
|
$key .= $chunk;
|
|
|
|
} while (\strlen($key) < Process::KEY_LENGTH);
|
2018-10-11 01:31:34 +02:00
|
|
|
|
2018-10-06 17:05:49 +02:00
|
|
|
if (!$socket = \stream_socket_client($uri, $errno, $errstr, 5, \STREAM_CLIENT_CONNECT)) {
|
2018-10-25 05:35:27 +02:00
|
|
|
\trigger_error("Could not connect to IPC socket", E_USER_ERROR);
|
2018-10-21 17:03:26 +02:00
|
|
|
exit(1);
|
2018-10-06 17:05:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$channel = new Sync\ChannelledSocket($socket, $socket);
|
|
|
|
|
2018-10-11 01:31:34 +02:00
|
|
|
try {
|
2019-01-04 23:58:05 +01:00
|
|
|
Promise\wait($channel->send($key));
|
2018-10-11 01:31:34 +02:00
|
|
|
} catch (\Throwable $exception) {
|
2018-10-25 05:35:27 +02:00
|
|
|
\trigger_error("Could not send key to parent", E_USER_ERROR);
|
2018-10-21 17:03:26 +02:00
|
|
|
exit(1);
|
2018-10-11 01:31:34 +02:00
|
|
|
}
|
|
|
|
|
2017-12-10 22:37:33 +01:00
|
|
|
try {
|
2018-10-15 07:15:56 +02:00
|
|
|
if (!isset($argv[0])) {
|
|
|
|
throw new \Error("No script path given");
|
|
|
|
}
|
2017-12-10 22:37:33 +01:00
|
|
|
|
2018-10-15 07:15:56 +02:00
|
|
|
if (!\is_file($argv[0])) {
|
|
|
|
throw new \Error(\sprintf("No script found at '%s' (be sure to provide the full path to the script)", $argv[0]));
|
|
|
|
}
|
2017-12-10 22:37:33 +01:00
|
|
|
|
2018-10-15 07:15:56 +02:00
|
|
|
// Protect current scope by requiring script within another function.
|
|
|
|
$callable = (function () use ($argc, $argv) { // Using $argc so it is available to the required script.
|
|
|
|
return require $argv[0];
|
2017-12-10 22:37:33 +01:00
|
|
|
})();
|
|
|
|
|
2018-10-15 07:15:56 +02:00
|
|
|
if (!\is_callable($callable)) {
|
|
|
|
throw new \Error(\sprintf("Script '%s' did not return a callable function", $argv[0]));
|
|
|
|
}
|
|
|
|
|
2019-01-04 23:58:05 +01:00
|
|
|
$result = new Sync\ExitSuccess(Promise\wait(call($callable, $channel)));
|
2017-12-10 22:37:33 +01:00
|
|
|
} catch (\Throwable $exception) {
|
|
|
|
$result = new Sync\ExitFailure($exception);
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2019-01-04 23:58:05 +01:00
|
|
|
Promise\wait(call(function () use ($channel, $result) {
|
|
|
|
try {
|
|
|
|
yield $channel->send($result);
|
|
|
|
} catch (Sync\SerializationException $exception) {
|
|
|
|
// Serializing the result failed. Send the reason why.
|
|
|
|
yield $channel->send(new Sync\ExitFailure($exception));
|
|
|
|
}
|
|
|
|
}));
|
2017-12-10 22:37:33 +01:00
|
|
|
} catch (\Throwable $exception) {
|
2018-12-30 20:08:38 +01:00
|
|
|
\trigger_error("Could not send result to parent; be sure to shutdown the child before ending the parent", E_USER_ERROR);
|
2018-10-21 17:03:26 +02:00
|
|
|
exit(1);
|
2017-12-10 22:37:33 +01:00
|
|
|
}
|
2019-01-04 23:58:05 +01:00
|
|
|
})();
|