/** * Runs the thread code and the initialized function. * * @codeCoverageIgnore Only executed in thread. */ public function run() { /* First thing we need to do is re-initialize the class autoloader. If * we don't do this first, any object of a class that was loaded after * the thread started will just be garbage data and unserializable * values (like resources) will be lost. This happens even with * thread-safe objects. */ foreach (get_declared_classes() as $className) { if (strpos($className, 'ComposerAutoloaderInit') === 0) { // Calling getLoader() will register the class loader for us $className::getLoader(); break; } } Loop\loop($loop = Loop\create(false)); // Disable signals in thread. // At this point, the thread environment has been prepared so begin using the thread. try { $channel = new ChannelledStream(new DuplexPipe($this->socket, false)); } catch (\Throwable $exception) { return; // Parent has destroyed Thread object, so just exit. } $coroutine = new Coroutine($this->execute($channel)); $coroutine->done(); $timer = $loop->timer(self::KILL_CHECK_FREQUENCY, true, function () use($loop) { if ($this->killed) { $loop->stop(); } }); $timer->unreference(); $loop->run(); }
/** * Starts the context execution. * * @throws \Icicle\Concurrent\Exception\ForkException If forking fails. * @throws \Icicle\Stream\Exception\FailureException If creating a socket pair fails. */ public function start() { if (0 !== $this->oid) { throw new StatusError('The context has already been started.'); } list($parent, $child) = Stream\pair(); switch ($pid = pcntl_fork()) { case -1: // Failure throw new ForkException('Could not fork process!'); case 0: // Child // @codeCoverageIgnoreStart // Create a new event loop in the fork. Loop\loop($loop = Loop\create(false)); $channel = new ChannelledStream($pipe = new DuplexPipe($parent)); fclose($child); $coroutine = new Coroutine($this->execute($channel)); $coroutine->done(); try { $loop->run(); $code = 0; } catch (\Throwable $exception) { $code = 1; } $pipe->close(); exit($code); // @codeCoverageIgnoreEnd // @codeCoverageIgnoreEnd default: // Parent $this->pid = $pid; $this->oid = posix_getpid(); $this->channel = new ChannelledStream($this->pipe = new DuplexPipe($child)); fclose($parent); } }
/** * @param \Icicle\Loop\Loop|null $loop */ public function __construct(Loop\Loop $loop = null) { $this->loop = $loop ?: Loop\loop(); }
public function setUp() { Loop\loop(new Loop\SelectLoop()); }