public function countFiles(array $files, $countTests) { $chunkSize = ceil(count($files) / $this->_cores); $chunks = array_chunk($files, $chunkSize); $forks = array(); $sockets = array(); for ($i = 0; $i < $this->_cores; $i++) { if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets) === false) { echo "socket_create_pair failed. Reason: " . socket_strerror(socket_last_error()); } $this->socketPairs[] = $sockets; $forks[] = $pid = pcntl_fork(); if ($pid === 0) { parent::countFiles($chunks[$i], $countTests); $data = array('count' => $this->count, 'namespaces' => $this->namespaces); $dataString = serialize($data); socket_set_nonblock($sockets[0]); if (socket_write($sockets[0], str_pad($dataString, self::MESSAGE_LENGTH), self::MESSAGE_LENGTH) === false) { throw new Exception("socket_write() failed. Reason: " . socket_strerror(socket_last_error($sockets[0]))); } socket_close($sockets[0]); die; } } do { pcntl_wait($status); array_pop($forks); } while (count($forks) > 0); for ($i = 0; $i < $this->_cores; $i++) { $sockets = $this->socketPairs[$i]; $childMessage = ''; $childMessage = socket_read($sockets[1], self::MESSAGE_LENGTH); $data = unserialize(trim($childMessage)); socket_close($sockets[1]); $this->mergeAndSumCount($data['count']); $this->mergeNamespaces($data['namespaces']); // $this->mergeDirectories($data['directories']); } // need to find some way to pass the number of directories from the child to the paent so // we don't have to do this again // same with namespaces which are also a object variable $count = $this->getCount($countTests); foreach ($files as $file) { $directory = dirname($file); if (!isset($directories[$directory])) { $directories[$directory] = TRUE; } } $count['directories'] = count($directories) - 1; return $count; }
function async($thunk) { // By creating a socket pair, we have a channel of communication // between PHP processes socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets); list($parent, $child) = $sockets; if (($pid = pcntl_fork()) == 0) { // We're in the child process now socket_close($child); // Call the thunk, serialize the returned value, and send it // through the channel we created (ie. to the parent process) socket_write($parent, serialize(call_user_func($thunk))); socket_close($parent); exit; // We're done so we can exit here } socket_close($parent); return array($pid, $child); // This can treated as a "thread handle" }
function pleac_Communicating_Between_Related_Processes() { // PHP supports fork/exec/wait but not pipe. However, it does // support socketpair, which can do everything pipes can as well // as bidirectional communication. The original recipes have been // modified here to use socketpair only. // ----------------------------- // pipe1 - use socketpair and fork so parent can send to child $sockets = array(); if (!socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets)) { die(socket_strerror(socket_last_error())); } list($reader, $writer) = $sockets; $pid = pcntl_fork(); if ($pid == -1) { die('cannot fork'); } elseif ($pid) { socket_close($reader); $line = sprintf("Parent Pid %d is sending this\n", getmypid()); if (!socket_write($writer, $line, strlen($line))) { socket_close($writer); die(socket_strerror(socket_last_error())); } socket_close($writer); pcntl_waitpid($pid, $status); } else { socket_close($writer); $line = socket_read($reader, 1024, PHP_NORMAL_READ); printf("Child Pid %d just read this: `%s'\n", getmypid(), rtrim($line)); socket_close($reader); // this will happen anyway exit(0); } // ----------------------------- // pipe2 - use socketpair and fork so child can send to parent $sockets = array(); if (!socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets)) { die(socket_strerror(socket_last_error())); } list($reader, $writer) = $sockets; $pid = pcntl_fork(); if ($pid == -1) { die('cannot fork'); } elseif ($pid) { socket_close($writer); $line = socket_read($reader, 1024, PHP_NORMAL_READ); printf("Parent Pid %d just read this: `%s'\n", getmypid(), rtrim($line)); socket_close($reader); pcntl_waitpid($pid, $status); } else { socket_close($reader); $line = sprintf("Child Pid %d is sending this\n", getmypid()); if (!socket_write($writer, $line, strlen($line))) { socket_close($writer); die(socket_strerror(socket_last_error())); } socket_close($writer); // this will happen anyway exit(0); } // ----------------------------- // pipe3 and pipe4 demonstrate the use of perl's "forking open" // feature to reimplement pipe1 and pipe2. pipe5 uses two pipes // to simulate socketpair. Since PHP supports socketpair but not // pipe, and does not have a "forking open" feature, these // examples are skipped here. // ----------------------------- // pipe6 - bidirectional communication using socketpair $sockets = array(); if (!socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets)) { die(socket_strerror(socket_last_error())); } list($child, $parent) = $sockets; $pid = pcntl_fork(); if ($pid == -1) { die('cannot fork'); } elseif ($pid) { socket_close($parent); $line = sprintf("Parent Pid %d is sending this\n", getmypid()); if (!socket_write($child, $line, strlen($line))) { socket_close($child); die(socket_strerror(socket_last_error())); } $line = socket_read($child, 1024, PHP_NORMAL_READ); printf("Parent Pid %d just read this: `%s'\n", getmypid(), rtrim($line)); socket_close($child); pcntl_waitpid($pid, $status); } else { socket_close($child); $line = socket_read($parent, 1024, PHP_NORMAL_READ); printf("Child Pid %d just read this: `%s'\n", getmypid(), rtrim($line)); $line = sprintf("Child Pid %d is sending this\n", getmypid()); if (!socket_write($parent, $line, strlen($line))) { socket_close($parent); die(socket_strerror(socket_last_error())); } socket_close($parent); exit(0); } }
/** * Creates a pair of indistinguishable sockets and stores them in an array. * * <p>Creates two connected and indistinguishable sockets. This function is commonly used in IPC (InterProcess * Communication).</p> * * @param int $domain <p>The domain parameter specifies the protocol family to be used by the socket. See * <code>create()</code> for the full list.</p> * @param int $type <p>The type parameter selects the type of communication to be used by the socket. See * <code>create()</code> for the full list.</p> * @param int $protocol <p>The protocol parameter sets the specific protocol within the specified domain to be used * when communicating on the returned socket. The proper value can be retrieved by name by using * <code>getprotobyname()</code>. If the desired protocol is TCP, or UDP the corresponding constants * <code>SOL_TCP</code>, and <code>SOL_UDP</code> can also be used. See <code>create()</code> for the full list of * supported protocols. * * @throws Exception\SocketException If the creation of the php sockets is not successful. * * @see Socket::create() * * @return Socket[] An array of Socket objects containing identical sockets. */ public static function createPair($domain, $type, $protocol) { $array = []; $return = @socket_create_pair($domain, $type, $protocol, $array); if ($return === false) { throw new SocketException(); } $sockets = self::constructFromResources($array); foreach ($sockets as $socket) { $socket->domain = $domain; $socket->type = $type; $socket->protocol = $protocol; } return $sockets; }
/** * */ public function __construct() { $this->tty_fd = fopen("/dev/tty", "r+b"); if (!$this->tty_fd) { throw new InitalizationException("Cannot open /dev/tty"); } $terminalDetector = new TerminalDetector(); $this->terminal = $terminalDetector->detect(); socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $this->winch_sockets); $this->old_tty_settings = $this->getTtySettings(); $this->setTTYSettings(array('-ignbrk', '-brkint', '-ignpar', '-parmrk', '-inpck', '-istrip', '-inlcr', '-igncr', '-icrnl', '-ixon', '-ixoff', '-iuclc', '-ixany', '-imaxbel', '-opost', '-isig', '-icanon', '-iexten', '-parenb', 'cs8', 'time', '0', 'min', '0')); $this->input_buffer = new ByteBuffer(128, $this->terminal); $this->output_buffer = new ByteBuffer(32 * 1024, $this->terminal); $this->output_buffer->putsFunc(TerminalFunc::T_ENTER_CA); $this->output_buffer->putsFunc(TerminalFunc::T_ENTER_KEYPAD); $this->output_buffer->putsFunc(TerminalFunc::T_HIDE_CURSOR); $this->sendClear(); $this->updateTerminalSize(); pcntl_signal(SIGWINCH, array($this, 'sigwinchhandler')); $this->back_buffer = new CellBuffer($this->term_width, $this->term_height, $this->foreground, $this->background); $this->front_buffer = new CellBuffer($this->term_width, $this->term_height, $this->foreground, $this->background); }
/** * Execute a Closure as another process in the background while showing a * status update. The status update can be an indefinite spinner or a string * periodically sent from the background process, depending on whether the * provided Closure object has a $socket parameter or not. Messaging to the * main process is done by socket_* functions. The return value is either * the return value of the background process, or false if the process fork * failed. * * @param callable $callable Closure object * @return bool|int * @throws \Exception */ public static function work(\Closure $callable) { if (!extension_loaded('pcntl')) { throw new \Exception('pcntl extension required'); } if (!extension_loaded('sockets')) { throw new \Exception('sockets extension required'); } $spinner = array('|', '/', '-', '\\'); $i = 0; $l = count($spinner); $delay = 100000; $func = new \ReflectionFunction($callable); $socket = (bool) $func->getNumberOfParameters(); if ($socket) { $sockets = array(); if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets) === false) { return false; } } $pid = pcntl_fork(); if ($pid > 0) { $done = false; $retval = 0; pcntl_signal(SIGCHLD, function () use($pid, &$done, &$retval) { $child_pid = pcntl_waitpid($pid, $status); if (pcntl_wifexited($status)) { $retval = pcntl_wexitstatus($status); } $done = true; }); if ($socket) { $text = ''; while (!$done) { $r = array($sockets[1]); $w = null; $e = null; if ($status = socket_select($r, $w, $e, 0)) { $data = socket_read($sockets[1], 4096, PHP_NORMAL_READ); if ($data === false) { throw new \Exception(sprintf('socket write error %s', socket_strerror(socket_last_error($sockets[1])))); } echo str_repeat(chr(8), strlen($text)); $text = rtrim($data, "\n"); Console::stdout($text); } else { pcntl_signal_dispatch(); } usleep($delay); } echo str_repeat(chr(8), strlen($text)); socket_close($sockets[0]); socket_close($sockets[1]); } else { while (!$done) { pcntl_signal_dispatch(); echo $spinner[$i]; usleep($delay); echo chr(8); $i = $i === $l - 1 ? 0 : $i + 1; } } return $retval; } elseif ($pid === 0) { if ($socket) { call_user_func($callable, $sockets[0]); } else { call_user_func($callable); } exit; } else { // Unable to fork process. return false; } }
/** * Creates the worker pool (forks the children) * * Please close all open resources before running this function. * Child processes are going to close all open resources uppon exit, * leaving the parent process behind with invalid resource handles. * @param \QXS\WorkerPool\WorkerInterface $worker the worker, that runs future tasks * @throws \RuntimeException * @throws WorkerPoolException * @return WorkerPool */ public function create(WorkerInterface $worker) { if ($this->workerPoolSize <= 1) { $this->workerPoolSize = 2; } $this->parentPid = getmypid(); $this->worker = $worker; if ($this->created) { throw new WorkerPoolException('The pool has already been created.'); } $this->created = TRUE; // when adding signals use pcntl_signal_dispatch(); or declare ticks foreach ($this->signals as $signo) { pcntl_signal($signo, array($this, 'signalHandler')); } // no Semaphore attached? -> create one if (!$this->semaphore instanceof Semaphore) { $this->semaphore = new Semaphore(); $this->semaphore->create(Semaphore::SEM_RAND_KEY); } elseif (!$this->semaphore->isCreated()) { $this->semaphore->create(Semaphore::SEM_RAND_KEY); } ProcessDetails::setProcessTitle($this->parentProcessTitleFormat, array('basename' => basename($_SERVER['PHP_SELF']), 'fullname' => $_SERVER['PHP_SELF'], 'class' => get_class($this))); for ($i = 1; $i <= $this->workerPoolSize; $i++) { $sockets = array(); if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets) === FALSE) { // clean_up using posix_kill & pcntl_wait throw new \RuntimeException('socket_create_pair failed.'); break; } $processId = pcntl_fork(); if ($processId < 0) { // cleanup using posix_kill & pcntl_wait throw new \RuntimeException('pcntl_fork failed.'); break; } elseif ($processId === 0) { // WE ARE IN THE CHILD $this->workerProcesses = new ProcessDetailsCollection(); // we do not have any children $this->workerPoolSize = 0; // we do not have any children socket_close($sockets[1]); // close the parent socket $this->runWorkerProcess($worker, new SimpleSocket($sockets[0]), $i); } else { // WE ARE IN THE PARENT socket_close($sockets[0]); // close child socket // create the child $this->workerProcesses->addFree(new ProcessDetails($processId, new SimpleSocket($sockets[1]))); } } return $this; }
/** * Creates a pair of sockets * */ public static function create_pair($domain, $type, $protocol) { $created = @socket_create_pair($domain, $type, $protocol, $fd); if ($created === false) { throw new Socket_Exception("Failed to create socket pair", socket_last_error()); } $ret = array(new self($fd[0]), new self($fd[1])); return $ret; }
function index($aResult, $sDatabaseDSN) { $oDB =& DB::connect($sDatabaseDSN . '?new_link=true', array('persistent' => false)); if (PEAR::IsError($oDB)) { echo $oDB->getMessage() . "\n"; exit; } $oDB->setFetchMode(DB_FETCHMODE_ASSOC); $oDB->query("SET DateStyle TO 'sql,european'"); $oDB->query("SET client_encoding TO 'utf-8'"); if (!isset($aResult['index-estrate']) || $aResult['index-estrate'] < 1) { $aResult['index-estrate'] = 30; } if (getBlockingProcesses() > $aResult['max-blocking']) { echo "Too many blocking processes for index\n"; exit; } if ($aResult['index-instances'] > 1) { $aInstances = array(); for ($iInstance = 0; $iInstance < $aResult['index-instances']; $iInstance++) { $aInstances[$iInstance] = array('iPID' => null, 'hSocket' => null, 'bBusy' => false); socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $aSockets); $iPID = pcntl_fork(); if ($iPID == -1) { die('Could not fork Process'); } if (!$iPID) { // THIS IS THE CHILD PROCESS // Reconnect to database - reusing the same connection is not a good idea! $oDBChild =& DB::connect($sDatabaseDSN . '?new_link=true', array('persistent' => false)); if (PEAR::IsError($oDBChild)) { echo $oDBChild->getMessage() . "\n"; exit; } $oDBChild->setFetchMode(DB_FETCHMODE_ASSOC); $oDBChild->query("SET DateStyle TO 'sql,european'"); $oDBChild->query("SET client_encoding TO 'utf-8'"); socket_close($aSockets[1]); $hSocket = $aSockets[0]; while ($sRead = socket_read($hSocket, 1000, PHP_BINARY_READ)) { if ($sRead == 'EXIT') { break; } $aSector = unserialize($sRead); echo " - {$iInstance} processing " . $aSector['geometry_index'] . "\n"; indexSector($oDBChild, $aSector, $aResult['max-blocking'], $aResult['max-load']); socket_write($hSocket, 'DONE'); echo " - {$iInstance} finished " . $aSector['geometry_index'] . "\n"; } socket_close($hSocket); exit; // THIS IS THE END OF THE CHILD PROCESS } $aInstances[$iInstance]['iPID'] = $iPID; socket_close($aSockets[0]); socket_set_nonblock($aSockets[1]); $aInstances[$iInstance]['hSocket'] = $aSockets[1]; } } // Re-index the new items if (!isset($aResult['index-rank']) || !$aResult['index-rank']) { $aResult['index-rank'] = 0; } for ($i = $aResult['index-rank']; $i <= 30; $i++) { echo "Rank: {$i}"; $iStartTime = date('U'); flush(); $sSQL = 'select geometry_index(geometry,indexed,name),count(*) from placex where rank_search = ' . $i . ' and indexed = false and name is not null group by geometry_index(geometry,indexed,name)'; $sSQL .= ' order by count desc'; $aAllSectors = $oDB->getAll($sSQL); if (PEAR::isError($aAllSectors)) { var_dump($aAllSectors); exit; } $iTotalNum = 0; foreach ($aAllSectors as $aSector) { $iTotalNum += $aSector['count']; } $iTotalLeft = $iTotalNum; echo ", total to do: {$iTotalNum} \n"; flush(); $fRankStartTime = time(); $iTotalDone = 0; $fRate = $aResult['index-estrate']; foreach ($aAllSectors as $aSector) { $aSector['rank'] = $i; if ($aSector['rank'] == 21 && $aSector['geometry_index'] == 617467) { echo "Skipping sector 617467 @ 21 due to issue\n"; continue; } while (getBlockingProcesses() > $aResult['max-blocking'] || getLoadAverage() > $aResult['max-load']) { echo "System busy, pausing indexing...\n"; sleep(60); } $iEstSeconds = (int) ($iTotalLeft / $fRate); $iEstDays = floor($iEstSeconds / (60 * 60 * 24)); $iEstSeconds -= $iEstDays * (60 * 60 * 24); $iEstHours = floor($iEstSeconds / (60 * 60)); $iEstSeconds -= $iEstHours * (60 * 60); $iEstMinutes = floor($iEstSeconds / 60); $iEstSeconds -= $iEstMinutes * 60; $iNum = $aSector['count']; $sRate = round($fRate, 1); echo $aSector['geometry_index'] . ": {$iNum}, {$iTotalLeft} left. Est. time remaining (rank {$i}) d:{$iEstDays} h:{$iEstHours} m:{$iEstMinutes} s:{$iEstSeconds} @ {$sRate} per second\n"; flush(); if ($aResult['index-instances'] > 1) { // Wait for a non-busy socket while (true) { for ($iInstance = 0; $iInstance < $aResult['index-instances']; $iInstance++) { if (!$aInstances[$iInstance]['bBusy']) { break 2; } $sRead = socket_read($aInstances[$iInstance]['hSocket'], 10, PHP_BINARY_READ); if ($sRead == 'DONE') { $aInstances[$iInstance]['bBusy'] = false; $iTotalDone += $iNum; $iTotalLeft -= $iNum; break 2; } } usleep(1000); } echo "Dispatch to {$iInstance} (" . $aInstances[$iInstance]['iPID'] . ")\n"; socket_write($aInstances[$iInstance]['hSocket'], serialize($aSector)); $aInstances[$iInstance]['bBusy'] = true; } else { indexSector($oDB, $aSector, $aResult['max-blocking'], $aResult['max-load']); $iTotalDone += $iNum; $iTotalLeft -= $iNum; } $fDuration = time() - $fRankStartTime; if ($fDuration) { $fRate = $iTotalDone / $fDuration; } else { $fRate = $aResult['index-estrate']; } } if ($aResult['index-instances'] > 1) { // Wait for a non-busy socket $bPending = true; while ($bPending) { $bPending = false; for ($iInstance = 0; $iInstance < $aResult['index-instances']; $iInstance++) { if ($aInstances[$iInstance]['bBusy']) { if (socket_read($aInstances[$iInstance]['hSocket'], 10, PHP_BINARY_READ) == 'DONE') { $aInstances[$iInstance]['bBusy'] = false; } else { $bPending = true; } } } if ($bPending) { usleep(1000000); } } } $iDuration = date('U') - $iStartTime; if ($iDuration && $iTotalNum) { echo "Finished Rank: {$i} in {$iDuration} @ " . $iTotalNum / $iDuration . " per second\n"; } } if ($aResult['index-instances'] > 1) { for ($iInstance = 0; $iInstance < $aResult['index-instances']; $iInstance++) { socket_write($aInstances[$iInstance]['hSocket'], 'EXIT'); socket_close($aInstances[$iInstance]['hSocket']); } } }
/** * Creates a pair of indistinguishable sockets and stores them in an array * * @param int $domain The protocol family to be used by the socket * @param int $type The type of communication to be used by the socket * @param int $protocol The specific protocol within the specified domain * @param array $fd Reference to an array in which the two socket resources will be inserted */ public final function socketCreatePair($domain, $type, $protocol, array &$fd) { return socket_create_pair($domain, $type, $protocol, $fd); }
function executeFork() { $this->output("Spawning {$this->procCount} child processes.\n"); $this->children = array(); for ($fork = 0; $fork < $this->procCount; $fork++) { $ok = socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $fd); if (!$ok) { throw new Exception("Could not create UNIX socket"); } $pid = pcntl_fork(); if ($pid == 0) { $this->isChild = true; foreach ($this->sockets as $old) { socket_close($old); } socket_close($fd[0]); break; } else { if ($pid == -1) { throw new Exception("Could not fork"); } socket_close($fd[1]); $this->children[] = $pid; $this->sockets[] = $fd[0]; } } if ($this->isChild) { $this->childNumber = $fork; $this->channel = $fd[1]; $this->executeWorker(); socket_close($this->channel); } else { $this->executeParent(); } }
/** * Parent child communcation sockets creation */ private function createParentChildComm() { $this->log(self::LOG_LEVEL_NORMAL, 'Preparing inter-process communication sockets...'); $sockets = array(); if (!socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets)) { throw new Exception(socket_strerror(socket_last_error())); } list($this->readerSocket, $this->writerSocket) = $sockets; socket_set_nonblock($this->readerSocket); socket_set_nonblock($this->writerSocket); }
/** * Forks and creates a socket pair for communication between parent and child process * * @param resource $socket * * @return int PID if master or 0 if child */ private function fork(&$socket) { $pair = []; if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $pair) === false) { $this->logger->error('{type}: Unable to create socket pair; ' . socket_strerror(socket_last_error($pair[0])), $this->logContext); exit(0); } $PID = Qless::fork(); if ($PID !== 0) { // MASTER $this->childProcesses++; $socket = $pair[0]; socket_close($pair[1]); socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, ['sec' => 0, 'usec' => 10000]); // wait up to 10ms to receive data return $PID; } $socket = $pair[1]; socket_close($pair[0]); $reserved = str_repeat('x', 20240); register_shutdown_function(function () use(&$reserved, $socket) { // shutting down if (null === ($error = error_get_last())) { return; } unset($reserved); $type = $error['type']; if (!isset(self::$ERROR_CODES[$type])) { return; } $this->logger->debug('Sending error to master', $this->logContext); $data = serialize($error); while (($len = socket_write($socket, $data)) > 0) { $data = substr($data, $len); } }); return $PID; }
<?php $sockets = array(); socket_create_pair(strtoupper(substr(PHP_OS, 0, 3)) == "WIN" ? AF_INET : AF_UNIX, SOCK_STREAM, 0, $sockets); $parent_sock = $sockets[0]; $child_sock = $sockets[1]; unset($sockets); $pid = pcntl_fork(); if ($pid == -1) { console("[-] Failed to fork"); define("THREADED", false); } elseif ($pid) { //Parent socket_close($child_sock); define("THREADED", true); define("CHILD", false); } else { //Child define("CHILD", true); socket_close($parent_sock); forking_runtime($child_sock); posix_kill(getmypid(), 9); } function forking_runtime($IOsock) { global $sock, $buffer, $chunks; socket_set_nonblock($IOsock); $last = time(); while ($sock) { buffer(); if ($last + 10 < time()) {
$this->bClosed = true; socket_shutdown($this->sckSocket); socket_close($this->sckSocket); } } /********************************************************************************* Main program start here *********************************************************************************/ /* Loading modules */ include _MODULES_PATH_ . "plugwise_usb.php"; writelog("Starting Main Program..."); foreach ($process as $processname => $module) { writelog("Creating IPC Socket for module {$processname} ..."); /* Trying to create socket pair */ /* Unable to create socket pair */ if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $process[$processname]["socket"]) === false) { writelog("socket_create_pair() a échoué. Raison : " . socket_strerror(socket_last_error())); } else { writelog("opening socket pair for {$processname} : OK"); /* Forking module*/ $pid = pcntl_fork(); /*********************************** /* Starting modules (child) ***********************************/ if (!$pid) { switch ($module["bootstrap"]) { case $process[$processname]["bootstrap"]: writelog("Starting module {$processname} ..."); include _MODULES_PATH_ . $process[$processname]["driver"]; writelog($process[$processname]["bootstrap"] . ": finished"); exit(0);
/** * Returns a new socket pair to simulate a real socket implementation. * * @throws \Exception Is thrown if the socket pair can't be craeted * @return array The socket pair */ public function getSocketPair() { // initialize the array for the socket pair $sockets = array(); // on Windows we need to use AF_INET $domain = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' ? AF_INET : AF_UNIX; // setup and return a new socket pair if (socket_create_pair($domain, SOCK_STREAM, 0, $sockets) === false) { throw new \Exception("socket_create_pair failed. Reason: " . socket_strerror(socket_last_error())); } // return the array with the socket pair return $sockets; }
/** * Initialize interprocess communication by setting up a pair * of sockets and returning them as an array. * * @return type */ private function ipc_init() { // windows needs AF_INET $domain = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' ? AF_INET : AF_UNIX; // create a socket pair for IPC $sockets = array(); if (socket_create_pair($domain, SOCK_STREAM, 0, $sockets) === false) { $this->log('socket_create_pair failed: ' . socket_strerror(socket_last_error()), self::LOG_LEVEL_CRIT); return false; } // return the sockets return $sockets; }
/** * Do something asynchronously. * * This neat little method sets up a UNIX socket for IPC, and then forks the current process. * The child is then able to talk to the parent, by way of a return value. * * @param callable A callback that is running in the forked instance. Anything returned will be captured by the main process. * * @return int The PID of the child process, for keeping track of your children. */ function async($function) { socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets); // IPC list($parent, $child) = $sockets; if (($pid = pcntl_fork()) == 0) { // In child process now socket_close($child); socket_write($parent, serialize(call_user_func($function, $this))); socket_close($parent); exit; } socket_close($parent); $this->child[$pid] = $child; return $pid; }
/* foreach (new \DirectoryIterator(__DIR__.'/concurrent/') as $item) { $name = (string) $item; if (!$item->isFile() || $name[0] == '.' || !ends_with($name, '.php')) continue; $tests[$testName] = require $item->getPathname(); } */ $tests = (require __DIR__ . '/concurrent-tests.php'); $parentPid = posix_getpid(); $workers = []; $failMessages = []; $pairs = []; for ($id = 0; $id < $config->workerCount; $id++) { if (!socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $pair)) { die; } $childPid = pcntl_fork(); if ($childPid) { socket_close($pair[1]); $workers[] = ['id' => $id, 'pid' => $childPid, 'socket' => $pair[0], 'socketId' => intval($pair[0])]; } else { socket_close($pair[0]); return run_worker_process($id, $pair[1]); } } return run_parent_process($workers, $argv); function run_parent_process($workers, $argv) { global $tests;
public function send($local, $remote) { $this->file_size = filesize($local); $sockets = array(); if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets) === false) { throw new Exception("socket_create_pair failed. Reason: " . socket_strerror(socket_last_error())); } $this->parent_socket = $sockets[1]; $this->child_socket = $sockets[0]; socket_set_nonblock($this->parent_socket); socket_set_nonblock($this->child_socket); $this->pid = pcntl_fork(); if ($this->pid == -1) { throw new Exception('Could not fork'); } else { if (!$this->pid) { //THIS IS THE CHILD PROCESS $this->signalInit(); $total_sent = 0; if ($in = fopen($local, 'r')) { $this->attempts = 0; $total_read = 0; $total_written = 0; $this->signalOpeningConnection($this->file_size); $trans_fp = fsockopen('127.0.0.1', '4000'); $response = fread($trans_fp, 28); if (strpos($response, '200') !== FALSE) { $this->signalGotConnection(); fwrite($trans_fp, $remote); $response = fread($trans_fp, 22); if (strpos($response, '100') !== FALSE) { $this->signalCreatedRemoteFile(); while (!feof($in) && !$this->cancelled()) { $read_count = 0; $cur_data = ''; $cur_data = fread($in, 1048576); $total_read += 1048576; $this->attempts = 0; $res = fwrite($trans_fp, $cur_data); $total_written += $res; $this->signalDataWritten($total_written); if ($res < strlen($cur_data)) { while ($res < strlen($cur_data) && !$this->cancelled()) { $length = strlen($cur_data) - $res; $cur_data = substr($cur_data, $res, $length); $res = fwrite($trans_fp, $cur_data); $this->signalDataWritten($total_written); $total_written += $res; $this->attempt(); } $this->resetAttempts(); } $response = fread($trans_fp, 24); while (strpos($response, '100') !== FALSE && !$this->cancelled() && $total_written > 0) { $trans = str_replace('100 ', '', trim($response)); $total_written -= $trans; $total_sent += $trans; if ($total_written) { $response = fread($trans_fp, 24); $this->attempt(); } } $total_written = 0; $this->resetAttempts(); } $this->resetAttempts(); } else { $this->signalCouldNotCreateRemoteFile(); } } else { $this->signalCouldNotGetConnection(); } fclose($trans_fp); } else { $this->signalNoLocalFile(); } $this->signalStopped($total_sent); } } }
/** * Run job in singlethread mode * * @param string Job unique identifier * * @return array {[pid],[name],[success],[start],[end],[result],[id]} */ private function runMultithread($jobUid) { $job = $this->jobs[$jobUid]; // get job start timestamp $start_timestamp = microtime(true); $this->logger->notice("Starting job " . $job['name'] . "(" . $job['id'] . ")"); $name = $job['name']; $id = $job['id']; $parameters = $job['parameters']; $task = $job['task']; $task_class = $job['class']; $this->ipc_array[$jobUid] = array(); // create a comm socket $socket = socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $this->ipc_array[$jobUid]); if ($socket === false) { $this->logger->error("No IPC communication, aborting", array("JOBUID" => $jobUid, "ERROR" => socket_strerror(socket_last_error()), "ERRID" => null)); array_push($this->completed_processes, array(null, $name, false, $start_timestamp, microtime(true), 'No IPC communication, exiting - ' . socket_strerror(socket_last_error()), $id, null)); return array("pid" => null, "name" => $name, "uid" => $jobUid, "timestamp" => $start_timestamp, "id" => $id); } list($reader, $writer) = $this->ipc_array[$jobUid]; $pid = pcntl_fork(); if ($pid == -1) { $this->logger->error("Could not fok job, aborting"); array_push($this->completed_processes, array(null, $name, false, $start_timestamp, microtime(true), 'Could not fok job', $id, null)); } elseif ($pid) { //PARENT will take actions on processes later self::adjustNiceness($pid, $this->logger); } else { socket_close($reader); $thetask = new $task_class($parameters, $this->logger, null, $name, $start_timestamp, true, $id); try { $result = $thetask->start(); $return = serialize(array("success" => $result["success"], "result" => $result["result"], "timestamp" => $result["timestamp"], "worklogid" => $result["worklogid"])); $exit = 0; } catch (TaskException $te) { $return = serialize(array("success" => false, "result" => $te->getMessage(), "timestamp" => $te->getEndTimestamp(), "worklogid" => $te->getWorklogId())); $exit = 1; } catch (Exception $e) { $return = serialize(array("success" => false, "result" => $e->getMessage(), "timestamp" => microtime(true), "worklogid" => null)); $exit = 1; } if (socket_write($writer, $return, strlen($return)) === false) { $this->logger->error("socket_write() failed ", array("ERROR" => socket_strerror(socket_last_error($writer)))); } socket_close($writer); exit($exit); } return array("pid" => $pid == -1 ? null : $pid, "name" => $name, "uid" => $jobUid, "id" => $id, "timestamp" => $start_timestamp); }
<?php $msg = "Hello"; $len = strlen($msg); $sockets = array(); socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets); socket_write($sockets[0], $msg, $len); $fdset = array(1 => $sockets[1]); $write = $excep = array(); socket_select($fdset, $write, $excep, 0, 100); print_r($fdset);
<?php $sockets = array(); $domain = AF_INET; socket_create_pair($domain, SOCK_STREAM, 0, $sockets); $write = null; $except = null; $time = -1; var_dump(socket_select($sockets, $write, $except, $time));
/** * Creates a pair of indistinguishable sockets and stores them in an array * * @param int $domain The domain parameter specifies the protocol * family to be used by the socket. See socket_create * for the full list. * @param int $type The type parameter selects the type of communication * to be used by the socket. See socket_create for the * full list. * @param int $protocol The protocol parameter sets the specific * protocol within the specified domain to be used * when communicating on the returned socket. The proper value can be retrieved by * name by using getprotobyname. If * the desired protocol is TCP, or UDP the corresponding constants * SOL_TCP, and SOL_UDP * can also be used. * @param array $fd Reference to an array in which the two socket resources will be inserted. * * @return bool */ public function socketCreatePair(int $domain, int $type, int $protocol, array &$fd) : bool { return socket_create_pair($domain, $type, $protocol, $fd); }
/** * Forks a new child * * @return string 'i_am_child' or 'i_am_master' */ private function _mp_fork() { $this->_debug("-----> " . __CLASS__ . '::' . __FUNCTION__ . '()', 9); // Create new socket pair first $r = socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $socketPair); if ($r === false) { throw new A2o_AppSrv_Exception('Unable to create a new socket pair'); } socket_set_nonblock($socketPair[0]); socket_set_nonblock($socketPair[1]); // Fork then $pid = pcntl_fork(); if ($pid == -1) { throw new A2o_AppSrv_Exception('Could not fork'); } if ($pid) { // We are a parent/master $workerId = $this->_mp_registerWorker($pid, $socketPair[0], $socketPair[1]); $this->_debug("worker with pid {$pid} registered"); usleep(100000); // Check if worker is still registered and tell it it's ID if ($this->_mp_isWorkerRegistered($workerId)) { $this->_ipc_tellWorker_workerId($workerId); } else { $this->___parent->__log("Worker id={$workerId} died unexpectedly"); } return 'i_am_master'; } else { // We are the child/worker //Assign the temporary variables $this->__tmp_listenStream = $this->_listenStream; $this->__tmp_masterSocket_read = $socketPair[0]; $this->__tmp_masterSocket_write = $socketPair[1]; return 'i_am_child'; } }
/** * * @param int $i * @throws \RuntimeException */ private function createWorker($i) { $sockets = array(); if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets) === FALSE) { // clean_up using posix_kill & pcntl_wait throw new \RuntimeException('socket_create_pair failed.'); return; } $processId = pcntl_fork(); if ($processId < 0) { // cleanup using posix_kill & pcntl_wait throw new \RuntimeException('pcntl_fork failed.'); return; } elseif ($processId === 0) { // WE ARE IN THE CHILD $this->workerProcesses = new ProcessDetailsCollection(); // we do not have any children $this->workerPoolSize = 0; // we do not have any children socket_close($sockets[1]); // close the parent socket $this->runWorkerProcess($this->worker, new SimpleSocket($sockets[0]), $i); } else { // WE ARE IN THE PARENT socket_close($sockets[0]); // close child socket // create the child $this->workerProcesses->addFree(new ProcessDetails($processId, new SimpleSocket($sockets[1]))); /** * Workaround to force destroy() to be called * @see https://github.com/qxsch/WorkerPool/issues/4 */ if (!isset($this->shutdownRegistered)) { register_shutdown_function([$this, 'destroy']); $this->shutdownRegistered = true; } } }
protected function getSockets() { $domain = strtoupper(substr(PHP_OS, 0, 3)) == 'WIN' ? AF_INET : AF_UNIX; socket_create_pair($domain, SOCK_STREAM, 0, $sockets); return $sockets; }
if (!socket_bind($rxsocket, "0.0.0.0", 44601)) { $errorcode = socket_last_error(); $errormsg = socket_strerror($errorcode); die("Could not bind socket : [{$errorcode}] {$errormsg} \n"); } echo "RX Socket bind OK \n"; do { $authok = false; //set authentication to default $r = socket_recvfrom($rxsocket, $buf, 512, 0, $remote_ip, $remote_port); // check data on socket if ($r > 0) { //wait for data to be received $r = 0; /* Setup socket pair */ if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $ary) === false) { echo "socket_create_pair() failed. Reason: " . socket_strerror(socket_last_error()); } $pid = pcntl_fork(); // fork process on new data received into child and parent if ($pid == -1) { die('could not fork'); } else { if ($pid) { // I am parent do not do anything and return to top $r = ..... socket_close($ary[0]); if (($data = socket_read($ary[1], strlen($remote_ip), PHP_BINARY_READ)) === $remote_ip) { array_push($authDevices, $data); //add the ip address to the array of authenticated devices // e('Unit authenticated ok '); }
function get_client_server() { $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $port = bind_random_port($server, "127.0.0.1"); var_dump($port != 0); var_dump(socket_listen($server)); $client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); var_dump(socket_connect($client, "127.0.0.1", $port)); $s = socket_accept($server); return array($client, $s); } /////////////////////////////////////////////////////////////////////////////// $s = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); var_dump($s); var_dump(create_listen_random_port() != 0); var_dump(socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $fds)); var_dump(count($fds)); var_dump(socket_get_option($s, SOL_SOCKET, SO_TYPE), SOCK_STREAM); list($client, $s) = get_client_server(); var_dump(socket_write($client, "hello world")); // this could fail with shorter returns, but it never does... var_dump(socket_read($s, 100)); list($client, $s) = get_client_server(); $reads = array($s); var_dump(socket_select($reads, $ignore1, $ignore2, 1, 0)); var_dump(socket_write($client, "next select will be 1")); $reads = array($s); var_dump(socket_select($reads, $ignore1, $ignore2, 1, 0)); list($client, $s) = get_client_server(); $text = "send/recv"; var_dump(socket_send($client, $text, 4, 0));
usleep(100000); $npid = pcntl_fork(); if ($npid == -1) { errexit("unable to pcntl_fork()"); } else { if ($npid) { techo("running in background"); exit(0); } } } if ($nb_loggers = $conf["global"]["loggerprocess"][0]) { // Prepare and spawn logger processes if specified techo("spawning loggers"); $sck_pair = array(); socket_create_pair(AF_UNIX, SOCK_DGRAM, 0, $sck_pair); $children_logsck =& $sck_pair[0]; $loggers_sck =& $sck_pair[1]; socket_set_nonblock($loggers_sck); spawn_loggers($nb_loggers); } else { // Be sure not to ask anything to loggers $conf["global"]["hostnamelookupsby"][0] = "server"; } if ($posix_av && $conf["global"]["pidfile"][0]) { $pidfile = $conf["global"]["pidfile"][0]; if ($f = fopen($pidfile, "w")) { fputs($f, (string) posix_getpid() . "\n"); fclose($f); } else { techo("WARN: unable to open pid file '" . $pidfile . "'", NW_EL_WARNING);