/** * Start Forking * * @param object $ProcessObject * @final */ public final function Run(&$ProcessObject) { // Check for ProcessObject existence if (!is_object($ProcessObject) || !$ProcessObject instanceof IProcess) { self::RaiseError("Invalid Proccess object", E_ERROR); } // Set class property $this->ProcessObject = $ProcessObject; $pid = posix_getpid(); if ($this->PIDDir) { $this->Logger->debug("Touch process PID file {$pid}"); @touch("{$this->PIDDir}/{$pid}"); } $this->Logger->debug("Executing 'OnStartForking' routine"); // Run routines before threading $this->ProcessObject->OnStartForking(); $this->Logger->debug("'OnStartForking' successfully executed."); if (count($this->ProcessObject->ThreadArgs) != 0) { // Add handlers to signals $this->SignalHandler->SetSignalHandlers(); $this->Logger->debug("Executing ProcessObject::ForkThreads()"); // Start Threading $this->ForkThreads(); // Wait while threads working $iteration = 1; while (true) { if (count($this->PIDs) == 0) { break; } if ($this->ChildProcessExecTimeLimit != 0) { foreach ($this->PIDs as $ipid => $ipid_info) { if ($ipid_info['start_time'] + $this->ChildProcessExecTimeLimit < time()) { $this->Logger->error(sprintf(_("Maximum execution time of %s seconds exceeded in %s. Killing process..."), $this->ChildProcessExecTimeLimit, get_class($this->ProcessObject) . "(Child PID: {$ipid_info['pid']})")); posix_kill($ipid, SIGKILL); } } } sleep(2); if ($iteration++ == 10) { $this->Logger->debug("Goin to MPWL. PIDs(" . implode(", ", array_keys($this->PIDs)) . ")"); // // Zomby not needed. // $pid = pcntl_wait($status, WNOHANG | WUNTRACED); if ($pid > 0) { $this->Logger->debug("MPWL: pcntl_wait() from child with PID# {$pid} (Exit code: {$status})"); foreach ((array) $this->PIDs as $ipid => $ipid_info) { if ($ipid == $pid) { if ($this->PIDDir) { $this->Logger->debug("Delete thread PID file {$pid}"); @unlink($this->PIDDir . "/" . $pid); } unset($this->PIDs[$ipid]); } } $this->ForkThreads(); } foreach ($this->PIDs as $ipid => $ipid_info) { $res = posix_kill($ipid, 0); $this->Logger->debug("MPWL: Sending 0 signal to {$ipid} = " . intval($res)); if ($res === FALSE) { $this->Logger->debug("MPWL: Deleting '{$ipid}' from PIDs queue"); if ($this->PIDDir) { $this->Logger->debug("Delete thread PID file {$ipid}"); @unlink($this->PIDDir . "/" . $ipid); } unset($this->PIDs[$ipid]); } } $iteration = 1; } } } else { $this->Logger->debug("ProcessObject::ThreadArgs is empty. Nothing to do."); } $pid = posix_getpid(); if ($this->PIDDir) { $this->Logger->debug("Delete Process PID file {$pid}"); @unlink("{$this->PIDDir}/{$pid}"); } $this->Logger->debug("All childs exited. Executing OnEndForking routine"); // Run routines after forking $this->ProcessObject->OnEndForking(); $this->Logger->debug("Main process complete. Exiting..."); exit; }
/** * Start Forking * * @param object $ProcessObject * @final */ final public function Run(&$ProcessObject) { // Check for ProcessObject existence if (!is_object($ProcessObject) || !($ProcessObject instanceof IProcess)) self::RaiseError("Invalid Proccess object", E_ERROR); // Set class property $this->ProcessObject = $ProcessObject; //Log::Log("Executing 'OnStartForking' routine", E_NOTICE); // Run routines before threading $this->ProcessObject->OnStartForking(); //Log::Log("'OnStartForking' successfully executed.", E_NOTICE); if (count($this->ProcessObject->ThreadArgs) == 0) { //Log::Log("ProcessObject::ThreadArgs is empty. Nothing to do.", E_NOTICE); return true; } //Log::Log("Executing ProcessObject::ForkThreads()", E_NOTICE); // Start Threading $this->ForkThreads(); // Wait while threads working $iteration = 1; while (true) { if (count($this->PIDs) == 0) break; sleep(2); if ($iteration++ == 10) { //Log::Log("Goin to MPWL. PIDs(".implode(", ", $this->PIDs).")", E_NOTICE); // // Zomby not needed. // $pid = pcntl_wait($status, WNOHANG | WUNTRACED); if ($pid > 0) { //Log::Log("MPWL: pcntl_wait() from child with PID# {$pid} (Exit code: {$status})", E_NOTICE); foreach((array)$this->PIDs as $kk=>$vv) { if ($vv == $pid) unset($this->PIDs[$kk]); } $this->ForkThreads(); } foreach ($this->PIDs as $k=>$pid) { $res = posix_kill($pid, 0); //Log::Log("MPWL: Sending 0 signal to {$pid} = ".intval($res), E_NOTICE); if ($res === FALSE) { //Log::Log("MPWL: Deleting '{$pid}' from PIDs query", E_NOTICE); unset($this->PIDs[$k]); } } $iteration = 1; } } //Log::Log("All childs exited. Executing OnEndForking routine", E_NOTICE); // Run routines after forking $this->ProcessObject->OnEndForking(); //Log::Log("Process complete. Exiting...", E_NOTICE); exit(); }