/** * @param Stream $stream * @return PromiseInterface */ public function handleInit(Stream $stream) { $this->stream = $stream; return new Promise(function (callable $fulfill, callable $reject) { $this->stream->once('data', function ($data) use($fulfill, $reject) { if (preg_match('/^ok\\b/i', $data)) { $this->stream->on('data', [$this, 'handleData']); $this->stream->on('error', [$this, 'handleError']); call_user_func($fulfill); } else { call_user_func($reject, trim($data)); } }); }); }
/** * gracefully shutdown connection by flushing all remaining data and closing stream * * @param Stream $stream */ public function endConnection(Stream $stream) { $tid = true; $loop = $this->loop; // cancel below timer in case connection is closed in time $stream->once('close', function () use(&$tid, $loop) { // close event called before the timer was set up, so everything is okay if ($tid === true) { // make sure to not start a useless timer $tid = false; } else { $loop->cancelTimer($tid); } }); // shut down connection by pausing input data, flushing outgoing buffer and then exit $stream->pause(); $stream->end(); // check if connection is not already closed if ($tid === true) { // fall back to forcefully close connection in 3 seconds if buffer can not be flushed $tid = $loop->addTimer(3.0, array($stream, 'close')); } }
$loop = LoopFactory::create(); $factory = new Factory($loop); $client = $factory->createClient(); $out = new Stream(STDOUT, $loop); $out->pause(); $stderr = new Stream(STDERR, $loop); $stderr->pause(); // unkown exit code by default $exit = 1; $client->execCreate($container, $cmd)->then(function ($info) use($client, $out, $stderr, &$exit) { $stream = $client->execStartStream($info['Id'], false, 'stderr'); $stream->pipe($out); // forward custom stderr event to STDERR stream $stream->on('stderr', function ($data) use($stderr, $stream) { if ($stderr->write($data) === false) { $stream->pause(); $stderr->once('drain', function () use($stream) { $stream->resume(); }); } }); $stream->on('error', 'printf'); // remember exit code of executed command once it closes $stream->on('close', function () use($client, $info, &$exit) { $client->execInspect($info['Id'])->then(function ($info) use(&$exit) { $exit = $info['ExitCode']; }, 'printf'); }); }, 'printf'); $loop->run(); exit($exit);