critical((string) $e); }); @cli_set_process_title('PHP Language Server'); // If XDebug is enabled, restart without it $xdebugHandler = new XdebugHandler('PHPLS'); $xdebugHandler->setLogger($logger); $xdebugHandler->check(); unset($xdebugHandler); if (!empty($options['tcp'])) { // Connect to a TCP server $address = $options['tcp']; $socket = stream_socket_client('tcp://' . $address, $errno, $errstr); if ($socket === false) { $logger->critical("Could not connect to language client. Error $errno\n$errstr"); exit(1); } stream_set_blocking($socket, false); $ls = new LanguageServer(new ProtocolStreamReader($socket), new ProtocolStreamWriter($socket)); Loop\run(); } elseif (!empty($options['tcp-server'])) { // Run a TCP Server $address = $options['tcp-server']; $tcpServer = stream_socket_server('tcp://' . $address, $errno, $errstr); if ($tcpServer === false) { $logger->critical("Could not listen on $address. Error $errno\n$errstr"); exit(1); } $logger->debug("Server listening on $address"); $pcntlAvailable = extension_loaded('pcntl'); if (!$pcntlAvailable) { $logger->notice('PCNTL is not available. Only a single connection will be accepted'); } while (($socket = stream_socket_accept($tcpServer, -1))) { $logger->debug('Connection accepted'); stream_set_blocking($socket, false); if ($pcntlAvailable) { // If PCNTL is available, fork a child process for the connection // An exit notification will only terminate the child process $pid = pcntl_fork(); if ($pid === -1) { $logger->critical('Could not fork'); exit(1); } elseif ($pid === 0) { // Child process $reader = new ProtocolStreamReader($socket); $writer = new ProtocolStreamWriter($socket); $reader->on('close', function () use ($logger) { $logger->debug('Connection closed'); }); $ls = new LanguageServer($reader, $writer); Loop\run(); // Just for safety exit(0); } } else { // If PCNTL is not available, we only accept one connection. // An exit notification will terminate the server $ls = new LanguageServer(new ProtocolStreamReader($socket), new ProtocolStreamWriter($socket)); Loop\run(); } } } else { // Use STDIO $logger->debug('Listening on STDIN'); stream_set_blocking(STDIN, false); $ls = new LanguageServer(new ProtocolStreamReader(STDIN), new ProtocolStreamWriter(STDOUT)); Loop\run(); }