ããšããšã¯ãåœç€Ÿã®ä»ã®ãã¹ãŠã®æªéã®ããã«ãCã§æžãããŠããŸããã ããããããã»ããµæéã®ããªãã®éšåïŒçŽ10ïŒ ïŒãç¡é§ã«ãªã£ãŠãããšããäºå®ã«çŽé¢ããŸãããããã¯ãã€ã³ã¿ãŒããªã¿ãŒã®èµ·åãšãã¬ãŒã ã¯ãŒã¯ã®ãã³ã¢ãã®ããŒãã§ãã ãããã£ãŠãã€ã³ã¿ãŒããªã¿ãŒãšãã¬ãŒã ã¯ãŒã¯ãäžåºŠã ãåæåã§ããããã«ããããã«ãPHPã§ããŒã¢ã³ãæžãçŽãããšã«ããŸããã ãããPhp rock sydãšåŒã³ãŸããïŒPhproxyd-PHP Proxy Daemonã以åã®CããŒã¢ã³ã«äŒŒãŠããŸãïŒã åã ã®ã¯ã©ã¹ãå®è¡ããèŠæ±ãåãå ¥ããåèŠæ±ã§forkïŒïŒãè¡ããåèµ·åã®å®è¡ã¹ããŒã¿ã¹ãå ±åããæ¹æ³ãç¥ã£ãŠããŸãã ãã®ã¢ãŒããã¯ãã£ã¯ããã¹ãŠã®åæåãããŠã£ã¶ãŒããã§1åè¡ããããåãããªã¯ãšã¹ãã®åŠçã«ãã§ã«é¢äžããŠããå ŽåãApache WebãµãŒããŒã¢ãã«ã«å€ãã®ç¹ã§äŒŒãŠããŸãã è¿œå ã®ããã³ããšããŠãCLIã§ãªãã³ãŒããã£ãã·ã¥ãæå¹ã«ããæ©äŒããããŸããããã¯ããã¹ãŠã®åããã¹ã¿ãŒããã»ã¹ãšåãå ±æã¡ã¢ãªã®é åãç¶æ¿ãããããæ£ããåäœããŸãã èµ·åèŠæ±ã®åŠçã®é 延ãæžããããã«ãäºåã«forkïŒïŒãè¡ãããšãã§ããŸãïŒããªãã©ãŒã¯ã¢ãã«ïŒããä»åã®å ŽåãforkïŒïŒã®é 延ã¯çŽ1ããªç§ã§ãããããã¯é©åã§ãã
ãã ããã³ãŒããé »ç¹ã«æŽæ°ããããããã®ããŒã¢ã³ãé »ç¹ã«åèµ·åããå¿ èŠããããŸããåèµ·åããªããšããã®ããŒã¢ã³ã«ããŒããããã³ãŒããå€ããªãå¯èœæ§ããããŸãã ååèµ·åã«ã¯ããšã³ããŠãŒã¶ãŒã«å¯ŸãããµãŒãã¹æåŠïŒããŒã¢ã³ã¯ã¯ã©ãŠãã ãã§ãªãããµã€ãã®äžéšã«ã圹ç«ã€ïŒãªã©ãpeerã«ããæ¥ç¶ãªã»ããã®ã¿ã€ãã®ãšã©ãŒãå€æ°çºçãããããæ¢ã«ç¢ºç«ãããæ¥ç¶ã倱ãããšãªãããŒã¢ã³ãåèµ·åããæ¹æ³ãæ¢ãããšã«ããŸããã ããŒã¢ã³ã«å¯ŸããŠã°ã¬ãŒã¹ãã«ãªããŒããè¡ãããäžè¬çãªææ³ã1ã€ãããŸããfork-execãè¡ããããªãã¹ã³ãœã±ããããã®èšè¿°åãåå«ã«æž¡ãããŸãã ãããã£ãŠãæ°ããæ¥ç¶ã¯ããŒã¢ã³ã®æ°ããããŒãžã§ã³ã«ãã£ãŠåãå ¥ããããŸãããå€ãæ¥ç¶ã¯å€ãããŒãžã§ã³ã䜿çšããŠãå€æŽããããŸãã
ãã®èšäºã§ã¯ã ã°ã¬ãŒã¹ãã«ãªããŒãã®è€éãªããŒãžã§ã³ãæ€èšããŸããå€ãæ¥ç¶ã¯æ°ããããŒãžã§ã³ã®ããŒã¢ã³ã«ãã£ãŠåŒãç¶ãåŠçãããŸããããã以å€ã®å Žåã¯å€ãã³ãŒããå®è¡ãããããããã¯éèŠã§ãã
çè«
å§ãã«èããŠã¿ãŸãããïŒç§ãã¡ãåãåãããå¯èœæ§ã¯ãããŸããïŒ ãããããªãããããéæããæ¹æ³ã¯ïŒ
ããŒã¢ã³ã¯POSIXäºæã®Linuxã§å®è¡ãããããã次ã®ãªãã·ã§ã³ã䜿çšã§ããŸãã
- éããŠãããã¡ã€ã«ãšãœã±ããã¯ãã¹ãŠãéããŠããèšè¿°åã®çªå·ã«å¯Ÿå¿ããçªå·ã§ãã æšæºå ¥åãåºåãããã³ãšã©ãŒã¹ããªãŒã ã«ã¯ãããããèšè¿°å0ã1ãããã³2ããããŸãã
- éããŠãããã¡ã€ã«ããœã±ããããã€ãã®éã«å€§ããªéãã¯ãããŸããïŒããšãã°ãèªã¿åã/æžã蟌ã¿ã·ã¹ãã ã³ãŒã«ãšsendto / recvfromã䜿çšããŠãœã±ãããæäœã§ããŸãïŒã
- forkïŒïŒã·ã¹ãã ã³ãŒã«ãè¡ããããšãéããŠãããã¹ãŠã®èšè¿°åã¯ããã®çªå·ãšïŒãã¡ã€ã«å ã®ïŒèªã¿åã/æžã蟌ã¿äœçœ®ãä¿æãããç¶æ ã§ç¶æ¿ãããŸãã
- execveïŒïŒã·ã¹ãã ã³ãŒã«ãå®è¡ããããšãéããŠãããã¹ãŠã®èšè¿°åãç¶æ¿ãããããã«ããã»ã¹PIDããããã£ãŠãã®åãžã®ãã€ã³ããä¿åãããŸãã
- ãªãŒãã³ããã»ã¹èšè¿°åã®ãªã¹ãã¯ã/ dev / fdãã£ã¬ã¯ããªããå ¥æã§ããŸããLinuxã§ã¯ããã®ãã£ã¬ã¯ããªã¯/ proc / self / fdã«ã·ã³ããªãã¯ãªã³ã¯ãããŠããŸãã
ãããã£ãŠãç§ãã¡ã®ä»äºã¯å®çŸå¯èœã§ãããå€ãã®åªåãªãã«ä¿¡ããããçç±ããããŸãã ããã§ã¯å§ããŸãããã
PHPããã
æ®å¿µãªãããäœæ¥ãè€éã«ããå°ããªè©³çŽ°ã1ã€ãããŸããPHPã§ã¯ãã¹ããªãŒã ã®ãã¡ã€ã«èšè¿°åçªå·ãååŸããçªå·ã§ãã¡ã€ã«èšè¿°åãéãæ¹æ³ããããŸããïŒä»£ããã«ããã¡ã€ã«èšè¿°åã®ã³ããŒãéãããŸããåèµ·åæããã³åããã»ã¹ã®èµ·åæã«ãªãŒã¯ãçºçããªãããã«ããªãŒãã³èšè¿°åãæ éã«ç£èŠããŸãïŒã
ãŸããããã€ãã®å°ããªããããPHPã³ãŒãã«è¿œå ããŠãã¹ããªãŒã ããfdãååŸããæ©èœãè¿œå ããfopenïŒphpïŒ// fd / <num>ïŒãèšè¿°åã®ã³ããŒãéããªãããã«ããŸãïŒ2çªç®ã®å€æŽã¯ãçŸåšã®PHPã®åäœããããã£ãŠã代ããã«phpïŒ// fdraw / <num>ïŒãªã©ã®æ°ãããã¢ãã¬ã¹ããè¿œå ã§ããŸãã
ãããã³ãŒã
diff --git a/ext/standard/php_fopen_wrapper.cb/ext/standard/php_fopen_wrapper.c index f8d7bda..fee964c 100644 --- a/ext/standard/php_fopen_wrapper.c +++ b/ext/standard/php_fopen_wrapper.c @@ -24,6 +24,7 @@ #if HAVE_UNISTD_H #include <unistd.h> #endif +#include <fcntl.h> #include "php.h" #include "php_globals.h" @@ -296,11 +297,11 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, char *path, ch "The file descriptors must be non-negative numbers smaller than %d", dtablesize); return NULL; } - - fd = dup(fildes_ori); - if (fd == -1) { + + fd = fildes_ori; + if (fcntl(fildes_ori, F_GETFD) == -1) { php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, - "Error duping file descriptor %ld; possibly it doesn't exist: " + "File descriptor %ld invalid: " "[%d]: %s", fildes_ori, errno, strerror(errno)); return NULL; } diff --git a/ext/standard/streamsfuncs.cb/ext/standard/streamsfuncs.c index 0610ecf..14fd3b0 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -24,6 +24,7 @@ #include "ext/standard/flock_compat.h" #include "ext/standard/file.h" #include "ext/standard/php_filestat.h" +#include "ext/standard/php_fopen_wrappers.h" #include "php_open_temporary_file.h" #include "ext/standard/basic_functions.h" #include "php_ini.h" @@ -484,6 +485,7 @@ PHP_FUNCTION(stream_get_meta_data) zval *arg1; php_stream *stream; zval *newval; + int tmp_fd; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) { return; @@ -502,6 +504,9 @@ PHP_FUNCTION(stream_get_meta_data) add_assoc_string(return_value, "wrapper_type", (char *)stream->wrapper->wops->label, 1); } add_assoc_string(return_value, "stream_type", (char *)stream->ops->label, 1); + if (SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&tmp_fd, 1) && tmp_fd != -1) { + add_assoc_long(return_value, "fd", tmp_fd); + } add_assoc_string(return_value, "mode", stream->mode, 1);
çã«ããªã£ãŠããå Žåã¯ãstream_get_meta_dataïŒïŒã«ãã£ãŠè¿ãããçµæã«fdãã£ãŒã«ããè¿œå ããŸããïŒããšãã°ãzlibã¹ããªãŒã ã®å Žåãfdãã£ãŒã«ãã¯ååšããŸããïŒã ãŸããæž¡ããããã¡ã€ã«èšè¿°åããã®dupïŒïŒåŒã³åºããåçŽãªãã§ãã¯ã«çœ®ãæããŸããã æ®å¿µãªãããfcntlïŒïŒåŒã³åºãã¯POSIXåºæã§ããããããã®ã³ãŒãã¯Windowsçšã«å€æŽããªããšæ©èœããŸããããã®ãããå®å šãªãããã«ã¯ä»ã®OSçšã®è¿œå ã®ã³ãŒããã©ã³ããå«ãŸããå¿ èŠããããŸãã
åèµ·åãªãã·ã§ã³ã®ãªãããŒã¢ã³
ãŸããJSON圢åŒã§ãªã¯ãšã¹ããåä¿¡ããäœããã®åçãæäŸã§ããå°ããªãµãŒããŒãäœæããŸãã ããšãã°ããªã¯ãšã¹ãã«å«ãŸããé åå ã®èŠçŽ ã®æ°ãè¿ããŸãã
ããŒã¢ã³ã¯ããŒã31337ã§ãªãã¹ã³ããŸããçµæã¯æ¬¡ã®ããã«ãªããŸãã
$ telnet localhost 31337 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. {"hash":1} # "Request had 1 keys" {"hash":1,"cnt":2} # "Request had 2 keys"
stream_socket_serverïŒïŒã䜿çšããŠããŒãã®ãªãã¹ã³ãéå§ããstream_selectïŒïŒã䜿çšããŠèªã¿åã/æžã蟌ã¿ã®æºåãã§ããŠããèšè¿°åãå€å¥ããŸãã
ã·ã³ãã«ãªå®è£
ã³ãŒãïŒSimple.phpïŒ
<?php class Simple { const PORT = 31337; const SERVER_KEY = 'SERVER'; /** @var resource[] (client_id => stream) */ private $streams = []; /** @var string[] (client_id => read buffer) */ private $read_buf = []; /** @var string[] (client_id => write buffer) */ private $write_buf = []; /** @var resource[] (client_id => stream from which to read) */ private $read = []; /** @var resource[] (client_id => stream where to write) */ private $write = []; /** @var int Total connection count */ private $conn_count = 0; public function run() { $this->listen(); echo "Entering main loop\n"; $this->mainLoop(); } protected function listen() { $port = self::PORT; $ip_port = "0.0.0.0:$port"; $address = "tcp://$ip_port"; $server = stream_socket_server($address, $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN); if (!$server) { fwrite(STDERR, "stream_socket_server failed: $errno $errstr\n"); exit(1); } $this->read[self::SERVER_KEY] = $server; echo "Listening on $address\n"; } public function response($stream_id, $response) { $json_resp = json_encode($response); echo "stream$stream_id " . $json_resp . "\n"; $this->write($stream_id, $json_resp . "\n"); } public function write($stream_id, $buf) { $this->write_buf[$stream_id] .= $buf; if (!isset($this->write[$stream_id])) { $this->write[$stream_id] = $this->streams[$stream_id]; } } public function accept($server) { echo "Accepting new connection\n"; $client = stream_socket_accept($server, 1, $peername); $stream_id = ($this->conn_count++); if (!$client) { fwrite(STDERR, "Accept failed\n"); return; } stream_set_read_buffer($client, 0); stream_set_write_buffer($client, 0); stream_set_blocking($client, 0); stream_set_timeout($client, 1); $this->read_buf[$stream_id] = ''; $this->write_buf[$stream_id] = ''; $this->read[$stream_id] = $this->streams[$stream_id] = $client; echo "Connected stream$stream_id: $peername\n"; } private function disconnect($stream_id) { echo "Disconnect stream$stream_id\n"; unset($this->read_buf[$stream_id], $this->write_buf[$stream_id]); unset($this->streams[$stream_id]); unset($this->write[$stream_id], $this->read[$stream_id]); } private function handleRead($stream_id) { $buf = fread($this->streams[$stream_id], 8192); if ($buf === false || $buf === '') { echo "got EOF from stream$stream_id\n"; if (empty($this->write_buf[$stream_id])) { $this->disconnect($stream_id); } else { unset($this->read[$stream_id]); } return; } $this->read_buf[$stream_id] .= $buf; $this->processJSONRequests($stream_id); } private function processJSONRequests($stream_id) { if (!strpos($this->read_buf[$stream_id], "\n")) return; $requests = explode("\n", $this->read_buf[$stream_id]); $this->read_buf[$stream_id] = array_pop($requests); foreach ($requests as $req) { $res = json_decode(rtrim($req), true); if ($res !== false) { $this->response($stream_id, "Request had " . count($res) . " keys"); } else { $this->response($stream_id, "Invalid JSON"); } } } private function handleWrite($stream_id) { if (!isset($this->write_buf[$stream_id])) { return; } $wrote = fwrite($this->streams[$stream_id], substr($this->write_buf[$stream_id], 0, 65536)); if ($wrote === false) { fwrite(STDERR, "write failed into stream #$stream_id\n"); $this->disconnect($stream_id); return; } if ($wrote === strlen($this->write_buf[$stream_id])) { $this->write_buf[$stream_id] = ''; unset($this->write[$stream_id]); if (empty($this->read[$stream_id])) { $this->disconnect($stream_id); } } else { $this->write_buf[$stream_id] = substr($this->write_buf[$stream_id], $wrote); } } public function mainLoop() { while (true) { $read = $this->read; $write = $this->write; $except = null; echo "Selecting for " . count($read) . " reads, " . count($write) . " writes\n"; $n = stream_select($read, $write, $except, NULL); if (!$n) { fwrite(STDERR, "Could not stream_select()\n"); } if (count($read)) { echo "Can read from " . count($read) . " streams\n"; } if (count($write)) { echo "Can write to " . count($write) . " streams\n"; } if (isset($read[self::SERVER_KEY])) { $this->accept($read[self::SERVER_KEY]); unset($read[self::SERVER_KEY]); } foreach ($read as $stream_id => $_) { $this->handleRead($stream_id); } foreach ($write as $stream_id => $_) { $this->handleWrite($stream_id); } } } } $instance = new Simple(); $instance->run();
ãã®ããŒã¢ã³ã®ã³ãŒãã¯æšæºãè¶ ããŠããŸãããå®è£ ã®è©³çŽ°ã«æ³šæããããšæããŸãïŒç¹å®ã®æ¥ç¶ãåç §ããŠãã¹ãŠã®èªã¿åãããã³æžã蟌ã¿ãããã¡ãŒãä¿åããèŠæ±ãèªã¿åã£ãåãå Žæã§çŽæ¥èŠæ±ãåŠçããŸãã ãããã®èŠæ±ã®1ã€ãåèµ·åãããå¯èœæ§ããããããããã¯éèŠã§ãããã®å Žåã次ã®èŠæ±ã®åŠçã«ã¯è³ããŸããã ããã§ãããªã¯ãšã¹ãããŸã èªã¿åã£ãŠããªãããã次ååãèšè¿°åããã®stream_selectïŒïŒã¯åãçµæãè¿ããŸãã ãããã£ãŠãã³ãã³ããã³ãã©ãŒããçŽæ¥åèµ·åããŠãã1ã€ã®èŠæ±ã倱ãããããšã¯ãããŸããïŒè€æ°ã®ã³ãã³ããåãæ¥ç¶ã§åæã«éä¿¡ããããããã®ã³ãã³ãã®1ã€ãåèµ·åããå Žåãé€ãïŒã
ããã§ã¯ãããŒã¢ã³ã®åèµ·åãã©ã®ããã«ããŠå¯èœã«ããŸããïŒ
åèµ·åããã³ç¢ºç«ãããæ¥ç¶ãä¿åããããŒã¢ã³
æãåçŽãªäŸã§ã¯ãæçšãªããšãè¡ãæ¹æ³ãããããªãã£ãã®ã§ãæåã«èª¬æããæªéããŸã æžããŠã¿ãŸãããã 次ã®ãããªãã®ãååŸããŸãïŒã³ãã³ãã¯ãcommand_name [JSON-data]ãã®åœ¢åŒã§ããŒã¢ã³ã«éä¿¡ãããŸããçãã¯JSONã®åœ¢åŒã§ãïŒã
$ telnet localhost 31337 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. # restart # "Restarted successfully" # run {"hash":1,"params":[1,2,3],"class":"TestClass1"} # {"error_text":"OK"} # ( child TestClass1 ) restart "Restarted successfully" # : check {"hash":1} {"error_text":"Still running"} # 5 : TestClass1 check {"hash":1} {"retcode":0} # , free check {"hash":1} {"retcode":0} free {"hash":1} {"error_text":"OK"} restart "Restarted successfully" # , restart restart {"error_text":"Restarted successfully"} bye Connection closed by foreign host.
åèµ·åã®ã¢ã€ãã¢ã¯ç°¡åã§ããå¿ èŠãªãã¹ãŠã®æ å ±ãå«ããã¡ã€ã«ãäœæããèµ·åæã«ãããèªã¿åã£ãŠãéããŠãããã¡ã€ã«èšè¿°åã埩å ããããšããŸãã
æåã«ãåèµ·åãã¡ã€ã«ã«æžã蟌ãã³ãŒããèšè¿°ããŸãã
echo "Creating restart file...\n"; if (!$res = $this->getFdRestartData()) { fwrite(STDERR, "Could not get restart FD data, exiting, graceful restart is not supported\n"); exit(0); } /* Close all extra file descriptors that we do not know of, including opendir() descriptor :) */ $dh = opendir("/proc/self/fd"); $fds = []; while (false !== ($file = readdir($dh))) { if ($file[0] === '.') continue; $fds[] = $file; } foreach ($fds as $fd) { if (!isset($this->known_fds[$fd])) { fclose(fopen("php://fd/" . $fd, 'r+')); } } $contents = serialize($res); if (file_put_contents(self::RESTART_DIR . self::RESTART_FILENAME, $contents) !== strlen($contents)) { fwrite(STDERR, "Could not fully write restart file\n"); unlink(self::RESTART_DIR . self::RESTART_FILENAME); }
ããŒã¿é åãååŸããã³ãŒãïŒgetFdRestartDataïŒïŒé¢æ°ïŒã以äžã«ç€ºããŸãã
$res = []; foreach (self::$restart_fd_resources as $prop) { $res[$prop] = []; foreach ($this->$prop as $k => $v) { $meta = stream_get_meta_data($v); if (!isset($meta['fd'])) { fwrite(STDERR, "No fd in stream metadata for resource $v (key $k in $prop), got " . var_export($meta, true) . "\n"); return false; } $res[$prop][$k] = $meta['fd']; $this->known_fds[$meta['fd']] = true; } } foreach (self::$restart_fd_props as $prop) { $res[$prop] = $this->$prop; } return $res;
ã³ãŒãã§ã¯ã2çš®é¡ã®ããããã£ãããããšãèæ ®ããŠããŸãã
- æ¥ç¶ããããªãœãŒã¹ãå«ãããããã£ïŒ$ restart_fd_resources = ['read'ã 'write'ã 'streams']ã
- çã§ã·ãªã¢ã«åã§ããæ¥ç¶ã«é¢ãããããã¡ããã³ãã®ä»ã®æ å ±ãå«ãããããã£ïŒ$ restart_fd_props = ['read_buf'ã 'write_buf'ã 'conn_count']ã
ãŸããåèµ·åãã¡ã€ã«ã«ä¿åãããŠãããã¹ãŠã®fdãèšæ¶ããä»ã®ãã¹ãŠïŒååšããå ŽåïŒãéããŸããããããªããšããã¡ã€ã«èšè¿°åããªãŒã¯ããå¯èœæ§ãããããã§ãã
次ã«ãèµ·åæã«ãã®ãã¡ã€ã«ãããŒãããäœãèµ·ãããªãã£ããã®ããã«ãéããŠããèšè¿°åãåŒãç¶ã䜿çšããå¿ èŠããããŸã:)ã 2ã€ã®é¢æ°ïŒåèµ·åãã¡ã€ã«ã®èªã¿èŸŒã¿ãšãã¡ã€ã«èšè¿°åã«é¢ããæ å ±ã®ããŠã³ããŒãïŒã®ã³ãŒãã以äžã«ç€ºããŸãã
ãã¡ã€ã«ã®ããŠã³ããŒãïŒ
if (!file_exists(self::RESTART_DIR . self::RESTART_FILENAME)) { return; } echo "Restart file found, trying to adopt it\n"; $contents = file_get_contents(self::RESTART_DIR . self::RESTART_FILENAME); unlink(self::RESTART_DIR . self::RESTART_FILENAME); if ($contents === false) { fwrite(STDERR, "Could not read restart file\n"); return; } $res = unserialize($contents); if (!$res) { fwrite(STDERR, "Could not unserialize restart file contents"); return; } foreach (self::$restart_props as $prop) { if (!array_key_exists($prop, $res)) { fwrite(STDERR, "No property $prop in restart file\n"); continue; } $this->$prop = $res[$prop]; } $this->loadFdRestartData($res);
ãã¡ã€ã«èšè¿°åã®é åãå±éããŠæ»ãloadFdRestartDataïŒïŒé¢æ°ïŒ
$fd_resources = []; foreach (self::$restart_fd_resources as $prop) { if (!isset($res[$prop])) { fwrite(STDERR, "Property '$prop' is not present in restart fd resources\n"); continue; } $pp = []; foreach ($res[$prop] as $k => $v) { if (isset($fd_resources[$v])) { $pp[$k] = $fd_resources[$v]; } else { $fp = fopen("php://fd/" . $v, 'r+'); if (!$fp) { fwrite(STDERR, "Failed to open fd = $v, exiting\n"); exit(1); } stream_set_read_buffer($fp, 0); stream_set_write_buffer($fp, 0); stream_set_blocking($fp, 0); stream_set_timeout($fp, self::CONN_TIMEOUT); $fd_resources[$v] = $fp; $pp[$k] = $fp; } } $this->$prop = $pp; } foreach (self::$restart_fd_props as $prop) { if (!isset($res[$prop])) { fwrite(STDERR, "Property '$prop' is not present in restart fd properties\n"); continue; } $this->$prop = $res[$prop]; }
ãªãŒãã³ãã¡ã€ã«èšè¿°åã®read_bufferãšwrite_bufferãåèšå®ããã¿ã€ã ã¢ãŠããæ§æããŸãã å¥åŠãªããšã«ããããã®æäœã®åŸãPHPã¯ãããã®ãã¡ã€ã«èšè¿°åã«å¯ŸããŠïŒïŒãéãã«åãå ¥ãããããããœã±ããã§ããããšãç¥ããªããŠããéåžžã¯èªã¿åã/æžã蟌ã¿ãç¶ããŸãã
æåŸã«ãã¯ãŒã«ãŒã®å®è¡ã¹ããŒã¿ã¹ãèµ·åããã³è¿œè·¡ããããã®ããžãã¯ãèšè¿°ããå¿ èŠããããŸãã ããã¯èšäºã®ãããã¯ãšã¯é¢ä¿ããªããããããŒã¢ã³ã®å®å šãªå®è£ ã¯githubãªããžããªã«é 眮ãããŸãããªã³ã¯ã¯ä»¥äžã«ãããŸãã
ãããã«
ãã®ããããã®èšäºã§ã¯ãJSONãããã³ã«ãä»ããŠéä¿¡ããå®è¡ããã»ã¹ãç£èŠããªããå¥ã®ããã»ã¹ã§ä»»æã®ã¯ã©ã¹ãå®è¡ã§ããããŒã¢ã³ã®å®è£ ã«ã€ããŠèª¬æããŸããã åã ã®ã¯ã©ã¹ãå®è¡ããã«ã¯ã forkïŒïŒã¢ãã«ã䜿çšããŠã¯ãšãªãå®è¡ããããããªã¯ãšã¹ããåŠçããããã«ãã€ã³ã¿ãŒããªã¿ãŒãåèµ·åããŠãã¬ãŒã ã¯ãŒã¯ãããŒãããå¿ èŠã¯ãªããCLIã§ãªãã³ãŒããã£ãã·ã¥ã䜿çšããããšãå¯èœã«ãªããŸãã ã³ãŒããæŽæ°ãããã³ã«ããŒã¢ã³ãåèµ·åããå¿ èŠãããããããã®ããŒã¢ã³ãã¹ã ãŒãºã«åèµ·åããå¿ èŠããããŸãïŒåœç€Ÿã§ã¯ãã³ãŒãã¯ãããããã£ãã¯ã¹ãã®åœ¢åŒã§æ°åããšã«æŽæ°ãããããšããããŸãïŒã
åèµ·åã¯execveïŒïŒã·ã¹ãã ã³ãŒã«ãå®è¡ããããšã«ããè¡ããããã®çµæããã¹ãŠã®åå«ã¯èŠªã«ãã€ã³ãããããŸãŸã«ãªããŸãïŒããã»ã¹ã®PIDã¯execveïŒïŒã§å€æŽãããªãããïŒã éããŠãããã¡ã€ã«èšè¿°åããã¹ãŠä¿åãããããããã§ã«éããŠããæ¥ç¶ã®ãŠãŒã¶ãŒããã®èŠæ±ãåŒãç¶ãåŠçã§ããŸãã ãã¹ãŠã®ãããã¯ãŒã¯ãããã¡ãå®è¡äžã®åã«é¢ããæ å ±ãããã³éããŠããèšè¿°åã¯ãåå¥ã®åèµ·åãã¡ã€ã«ã«ä¿åãããããŒã¢ã³ã®æ°ããã€ã³ã¹ã¿ã³ã¹ã«ãã£ãŠèªã¿åããããã®åŸãæšæºã€ãã³ãã«ãŒãã§äœæ¥ãç¶è¡ãããŸãã
å®å šãªå®è£ ã³ãŒãã¯ãGitHubã®æ¬¡ã®ã¢ãã¬ã¹ã§èŠãããšãã§ããŸãïŒ github.com/badoo/habr/tree/master/phprocksyd
質åãææ¡ã説æãæè¿ããŸãã
ãããã
ãŠãŒãªãŠãŒããã¯ãã¹ã¬ããã£ãã
ãªãŒãPHPéçºè
ããã¥ãŒ