1<?php declare(strict_types=1); 2 3function curl_cli_server_start() { 4 $php_executable = getenv('TEST_PHP_EXECUTABLE') ?: PHP_BINARY; 5 $doc_root = __DIR__; 6 $router = "responder/get.inc"; 7 $cmd = [$php_executable, '-t', $doc_root, '-n', '-S', 'localhost:0', $router]; 8 $descriptorspec = array( 9 0 => STDIN, 10 1 => STDOUT, 11 2 => ['pipe', 'w'], 12 ); 13 $handle = proc_open($cmd, $descriptorspec, $pipes, $doc_root, null, array("suppress_errors" => true)); 14 15 // First, wait for the dev server to declare itself ready. 16 $bound = null; 17 stream_set_blocking($pipes[2], false); 18 for ($i = 0; $i < 60; $i++) { 19 usleep(50000); // 50ms per try 20 $status = proc_get_status($handle); 21 if (empty($status['running'])) { 22 echo "Server is not running\n"; 23 proc_terminate($handle); 24 exit(1); 25 } 26 27 while (($line = fgets($pipes[2])) !== false) { 28 if (preg_match('@PHP \S* Development Server \(https?://(.*?:\d+)\) started@', $line, $matches)) { 29 $bound = $matches[1]; 30 // Now that we've identified the listen address, close STDERR. 31 // Otherwise the pipe may clog up with unread log messages. 32 fclose($pipes[2]); 33 break 2; 34 } 35 } 36 } 37 if ($bound === null) { 38 echo "Server did not output startup message"; 39 proc_terminate($handle); 40 exit(1); 41 } 42 43 // Now wait for a connection to succeed. 44 // note: even when server prints 'Listening on localhost:8964...Press Ctrl-C to quit.' 45 // it might not be listening yet...need to wait until fsockopen() call returns 46 $error = "Unable to connect to server\n"; 47 for ($i=0; $i < 60; $i++) { 48 usleep(50000); // 50ms per try 49 $status = proc_get_status($handle); 50 $fp = @fsockopen("tcp://$bound"); 51 // Failure, the server is no longer running 52 if (!($status && $status['running'])) { 53 $error = "Server is not running\n"; 54 break; 55 } 56 // Success, Connected to servers 57 if ($fp) { 58 $error = ''; 59 break; 60 } 61 } 62 63 if ($fp) { 64 fclose($fp); 65 } 66 67 if ($error) { 68 echo $error; 69 proc_terminate($handle); 70 exit(1); 71 } 72 73 register_shutdown_function( 74 function($handle) { 75 proc_terminate($handle); 76 /* Wait for server to shutdown */ 77 for ($i = 0; $i < 60; $i++) { 78 $status = proc_get_status($handle); 79 if (!($status && $status['running'])) { 80 break; 81 } 82 usleep(50000); 83 } 84 }, 85 $handle 86 ); 87 88 return $bound; 89} 90