Ejemplo n.º 1
1
 /**
  * Handle parent registered sigchild callbacks.
  *
  * @param int $signal_number is the signal that called this function.
  * @access public
  */
 public function signal_handler_sigchild($signal_number)
 {
     // do not allow signals to interrupt this
     declare (ticks=0) {
         // reap all child zombie processes
         if (self::$parent_pid == getmypid()) {
             $status = '';
             do {
                 // get child pid that exited
                 $child_pid = pcntl_waitpid(0, $status, WNOHANG);
                 if ($child_pid > 0) {
                     // child exited
                     $identifier = false;
                     if (!isset($this->forked_children[$child_pid])) {
                         $this->log("Cannot find {$child_pid} in array! (This may be a subprocess not in our fork)", self::LOG_LEVEL_INFO);
                         continue;
                     }
                     $child = $this->forked_children[$child_pid];
                     $identifier = $child['identifier'];
                     // call exit function if and only if its declared */
                     if ($child['status'] == self::WORKER) {
                         $this->invoke_callback($this->parent_function_child_exited[$this->forked_children[$child_pid]['bucket']], array($child_pid, $this->forked_children[$child_pid]['identifier']), true);
                     }
                     // stop the child pid
                     $this->forked_children[$child_pid]['status'] = self::STOPPED;
                     $this->forked_children_count--;
                     // respawn helper processes
                     if ($child['status'] == self::HELPER && $child['respawn'] === true) {
                         $this->log('Helper process ' . $child_pid . ' died, respawning', self::LOG_LEVEL_INFO);
                         $this->helper_process_spawn($child['function'], $child['arguments'], $child['identifier'], true);
                     }
                     // Poll for results from any children
                     $this->post_results($child['bucket']);
                 } elseif ($child_pid < 0) {
                     // ignore acceptable error 'No child processes' given we force this signal to run potentially when no children exist
                     if (pcntl_get_last_error() == 10) {
                         continue;
                     }
                     // pcntl_wait got an error
                     $this->log('pcntl_waitpid failed with error ' . pcntl_get_last_error() . ':' . pcntl_strerror(pcntl_get_last_error()), self::LOG_LEVEL_DEBUG);
                 }
             } while ($child_pid > 0);
         }
     }
 }
Ejemplo n.º 2
0
 /**
  * Daemonize the current process so it can run in the background.
  *
  * If $pidfile is supplied, the process ID is written there.
  * Provide absolute path names for the parameters to avoid file not found errors or logs inside the source code folder.
  *
  * If an error occurred, a RuntimeException is thrown.
  *
  * @param string $pidfile File to write the process ID of the daemon to
  * @param string $stderr File to redirect STDERR to
  * @param string $stdout File to redirect STDOUT to
  * @param string $stdin File to read STDIN from
  * @throws \RuntimeException
  * @return true
  */
 public static function daemonize($pidfile = null, $stderr = '/dev/null', $stdout = '/dev/null', $stdin = '/dev/null')
 {
     // Allow only cli scripts to daemonize, otherwise you may confuse your webserver
     if (\php_sapi_name() !== 'cli') {
         throw new \RuntimeException('Can only daemonize a CLI process!');
     }
     self::checkPID($pidfile);
     self::reopenFDs($stdin, $stdout, $stderr);
     if (($pid1 = @\pcntl_fork()) < 0) {
         throw new \RuntimeException('Failed to fork, reason: "' . \pcntl_strerror(\pcntl_get_last_error()) . '"');
     } elseif ($pid1 > 0) {
         exit;
     }
     if (@posix_setsid() === -1) {
         throw new \RuntimeException('Failed to become session leader, reason: "' . \posix_strerror(\posix_get_last_error()) . '"');
     }
     if (($pid2 = @\pcntl_fork()) < 0) {
         throw new \RuntimeException('Failed to fork, reason: "' . \pcntl_strerror(\pcntl_get_last_error()) . '"');
     } elseif ($pid2 > 0) {
         exit;
     }
     chdir('/');
     umask(022);
     self::writePID($pidfile);
     return true;
 }
Ejemplo n.º 3
0
 /**
  * @param \Extended\Process\Runnable $child
  *      A runnable process to fork
  */
 public function fork(Runnable $child)
 {
     $this->pid = pcntl_fork();
     if ($this->pid == -1) {
         $error = pcntl_strerror(pcntl_get_last_error());
         throw new ProcessException('Unable to fork the process: ' . $error);
     } elseif ($this->pid) {
         return pcntl_wait($this->pid);
     }
     self::$buffer->append($child->run());
 }
Ejemplo n.º 4
0
 /**
  * Fork.
  *
  * fork() helper method for php-resque
  *
  * @see pcntl_fork()
  *
  * @return Process|null An instance of Process representing the child in the parent, or null in the child.
  * @throws \Resque\Component\Core\Exception\ResqueRuntimeException when cannot fork, or fork failed.
  */
 public function fork()
 {
     if (!function_exists('pcntl_fork')) {
         throw new ResqueRuntimeException('pcntl_fork is not available');
     }
     $this->setPidFromCurrentProcess();
     $pid = pcntl_fork();
     if ($pid === -1) {
         throw new ResqueRuntimeException(sprintf('Unable to fork child. %s', pcntl_strerror(pcntl_get_last_error())));
     }
     if (0 === $pid) {
         // Forked and we're the child, so return nothing.
         return null;
     }
     $child = new self($pid);
     return $child;
 }
Ejemplo n.º 5
0
 public function testWrite()
 {
     $path = '/tmp/tmp.log';
     $count = 100;
     $workers = 10;
     if (is_file($path)) {
         unlink($path);
     }
     $message = '';
     for ($i = 0; $i < 1000; ++$i) {
         $message .= uniqid();
     }
     $message .= PHP_EOL;
     $pids = [];
     for ($w = 0; $w < $workers; ++$w) {
         $pid = pcntl_fork();
         if (function_exists('pcntl_get_last_error')) {
             $error_number = pcntl_get_last_error();
             $error = "[{$error_number}] " . pcntl_strerror($error_number);
         } else {
             $error = var_export(error_get_last(), true);
         }
         $this->assertNotSame(-1, $pid, "Can't fork: " . $error);
         if ($pid) {
             $pids[] = $pid;
         } else {
             $writer = new AppenderStream($path);
             $writer->setUseLock(true);
             $writer->setUseLockShortMessage(true);
             for ($i = 0; $i < $count; ++$i) {
                 $writer->write(1, $message);
             }
             die;
         }
     }
     foreach ($pids as $p) {
         pcntl_waitpid($p, $status);
     }
     $this->assertSame(13001, strlen($message));
     $c = str_pad('', $count * $workers * strlen($message), $message);
     $this->assertSame($c, file_get_contents($path));
     if (is_file($path)) {
         unlink($path);
     }
 }
Ejemplo n.º 6
0
 /**
  * @param callable $callable
  * @param array    $arguments
  *
  * @throws \Brick\Process\ProcessException
  */
 public function __construct(callable $callable, array $arguments = [])
 {
     self::checkExtensions();
     $pid = @pcntl_fork();
     if ($pid < 0) {
         $errorCode = pcntl_get_last_error();
         $errorMessage = pcntl_strerror($errorCode);
         throw ProcessException::forkingError($errorCode, $errorMessage);
     }
     if ($pid) {
         // Parent
         $this->pid = $pid;
     } else {
         // Child
         call_user_func_array($callable, $arguments);
         exit(0);
     }
 }
Ejemplo n.º 7
0
 public function run()
 {
     if ($this->stopped) {
         return 0;
     }
     $pid = pcntl_fork();
     if ($pid < 0) {
         $errno = pcntl_get_last_error();
         throw new \RuntimeException("Cannot fork process, error = " . pcntl_strerror($errno));
     } elseif ($pid == 0) {
         // in child process
         $now = time();
         if ($now < $this->nextRun) {
             if ($this->traceEnabled) {
                 mdebug("Will wait %d seconds for next run of %s", $this->nextRun - $now, $this->name);
             }
             sleep($this->nextRun - $now);
         }
         // run using application
         $this->application->setAutoExit(false);
         // we will handle exit on our own
         $this->application->setCatchExceptions(false);
         // we will catch on our own
         try {
             $ret = $this->application->run($this->input, $this->output);
         } catch (\Exception $e) {
             mtrace($e, "Exception while running command {$this->name}", "error");
             $ret = AbstractDaemonSentinelCommand::EXIT_CODE_COMMON_ERROR;
         }
         // Check if we should alert
         if ($ret != AbstractDaemonSentinelCommand::EXIT_CODE_OK && $this->alert) {
             // alert in child process is better, because we can get more trace here
             malert("Daemon command %s failed with exit code = %d", $this->name, $ret);
             exit(AbstractDaemonSentinelCommand::EXIT_CODE_OK);
             // exit OK because alert is already sent
         } else {
             exit($ret);
         }
     } else {
         $this->lastRun = $this->nextRun;
         return $pid;
     }
 }
Ejemplo n.º 8
0
 /**
  * @param callable $callback
  * @param array $args
  * @throws Exception
  * @return int Child process PID
  */
 public static function run(callable $callback, $args = [])
 {
     if (!function_exists('pcntl_fork')) {
         throw new Exception('No pcntl is installed');
     }
     $pid = pcntl_fork();
     if (-1 == $pid) {
         throw new Exception('pcntl_fork() error: ' . pcntl_strerror(pcntl_get_last_error()));
     }
     if (0 != $pid) {
         return $pid;
     } else {
         register_shutdown_function(function () {
             ob_end_clean();
             posix_kill(getmypid(), SIGKILL);
         });
         if (empty($args)) {
             call_user_func($callback);
         } else {
             call_user_func_array($callback, $args);
         }
         exit(0);
     }
 }
Ejemplo n.º 9
0
/**
 * Runs a pulling job, creating several threads to do so.
 * @param  object $a The App instance.
 * @param  array  $pull_batch A batch of URL's to pull.
 * @param  string $db_host    DB host to connect to.
 * @param  string $db_user    DB user to connect with.
 * @param  string $db_pass    DB pass to connect with.
 * @param  mixed  $db_data    Nobody knows.
 * @param  mixed  $install    Maybe a boolean.
 * @return void
 */
function run_pulling_job($a, $pull_batch, $db_host, $db_user, $db_pass, $db_data, $install)
{
    //We need the scraper.
    require_once 'include/submit.php';
    //POSIX threads only.
    if (!function_exists('pcntl_fork')) {
        msg('Error: no pcntl_fork support. Are you running a different OS? Report an issue please.', true);
    }
    //Create the threads we need.
    $items = count($pull_batch);
    $threadc = min($a->config['syncing']['pulling_threads'], $items);
    //Don't need more threads than items.
    $threads = array();
    msg("Creating {$threadc} pulling threads for {$items} profiles.");
    //Build the threads.
    for ($i = 0; $i < $threadc; $i++) {
        $pid = pcntl_fork();
        if ($pid === -1) {
            msg('Error: something went wrong with the fork. ' . pcntl_strerror(), true);
        }
        //You're a child, go do some labor!
        if ($pid === 0) {
            pull_worker($i, $threadc, $pull_batch, $db_host, $db_user, $db_pass, $db_data, $install);
            exit;
        }
        //Store the list of PID's.
        if ($pid > 0) {
            $threads[] = $pid;
        }
    }
    //Wait for all child processes.
    $theading_problems = false;
    foreach ($threads as $pid) {
        pcntl_waitpid($pid, $status);
        if ($status !== 0) {
            $theading_problems = true;
            msg("Bad process return value {$pid}:{$status}");
        }
    }
    //If we did not have any "threading" problems.
    if (!$theading_problems) {
        //Reconnect
        global $db;
        $db = new dba($db_host, $db_user, $db_pass, $db_data, $install);
        //Create a query for deleting this queue.
        $where = array();
        foreach ($pull_batch as $item) {
            $where[] = dbesc($item['url']);
        }
        $where = "WHERE `url` IN ('" . implode("', '", $where) . "')";
        //Remove the items from queue.
        q("DELETE FROM `sync-pull-queue` {$where} LIMIT %u", count($pull_batch));
        msg('Removed items from pull queue.');
    }
}
Ejemplo n.º 10
0
 /**
  * update the process status
  * @param bool $block
  */
 public function updateStatus($block = false)
 {
     if (empty($this->pid)) {
         $message = "the process pid is null, so maybe the process is not started";
         throw new \RuntimeException($message);
     }
     if ($this->running === false) {
         return;
     }
     if ($block) {
         $res = pcntl_waitpid($this->pid, $status);
     } else {
         $res = pcntl_waitpid($this->pid, $status, WNOHANG | WUNTRACED);
     }
     if ($res === -1) {
         $message = "pcntl_waitpid failed. the process maybe available";
         throw new \RuntimeException($message);
     } elseif ($res === 0) {
         $this->running = true;
     } else {
         if (pcntl_wifsignaled($status)) {
             $this->term_signal = pcntl_wtermsig($status);
         }
         if (pcntl_wifstopped($status)) {
             $this->stop_signal = pcntl_wstopsig($status);
         }
         if (pcntl_wifexited($status)) {
             $this->exit_code = pcntl_wexitstatus($status);
         } else {
             $this->errno = pcntl_get_last_error();
             $this->errmsg = pcntl_strerror($this->errno);
         }
         $this->running = false;
     }
 }
Ejemplo n.º 11
0
 /**
  * Get system-specific signal handler
  *
  * @return callable
  */
 protected function getSignalHandler()
 {
     return function (SignalHandler $handler, $signal) {
         if (SIGKILL != $signal) {
             //do not redefine SIGKILL, for consistency
             pcntl_sigprocmask(SIG_UNBLOCK, [$signal]);
             if (!pcntl_signal($signal, [$handler, 'handle'])) {
                 $this->logger->error('Failed to register system signal ' . $signal . ': ' . pcntl_strerror(pcntl_get_last_error()));
             } else {
                 $this->logger->info('Registered system signal: ' . $signal);
             }
         }
     };
 }
Ejemplo n.º 12
0
$threadc = min($a->config['maintenance']['threads'], $items);
//Don't need more threads than items.
$threads = array();
//Debug...
if ($verbose) {
    echo "Creating {$threadc} maintainer threads for {$items} profiles." . PHP_EOL;
}
logger("Creating {$threadc} maintainer threads for {$items} profiles.");
for ($i = 0; $i < $threadc; $i++) {
    $pid = pcntl_fork();
    if ($pid === -1) {
        if ($verbose) {
            echo 'Error: something went wrong with the fork. ' . pcntl_strerror();
        }
        logger('Error: something went wrong with the fork. ' . pcntl_strerror());
        die('Error: something went wrong with the fork. ' . pcntl_strerror());
    }
    //You're a child, go do some labor!
    if ($pid === 0) {
        break;
    }
    //Store the list of PID's.
    if ($pid > 0) {
        $threads[] = $pid;
    }
}
//The work for child processes.
if ($pid === 0) {
    //Lets be nice, we're only doing maintenance here...
    pcntl_setpriority(5);
    //Get personal DBA's.
Ejemplo n.º 13
0
 /**
  * Str Error
  *
  * @param $errno Error Number
  *
  * @return string|bool Returns error description on success or FALSE on failure.
  */
 public function strError($errno)
 {
     return pcntl_strerror($errno);
 }
Ejemplo n.º 14
0
 /**
  *
  * Shutdown function is call if script terminates try to make a restart if needed
  *
  * Prepare the job for start
  *
  * @internal param int the signal that terminates the job
  */
 public function shutdown()
 {
     $args = func_get_args();
     //Put last error to log if one
     $lasterror = error_get_last();
     if ($lasterror['type'] == E_ERROR or $lasterror['type'] == E_PARSE or $lasterror['type'] == E_CORE_ERROR or $lasterror['type'] == E_CORE_WARNING or $lasterror['type'] == E_COMPILE_ERROR or $lasterror['type'] == E_COMPILE_WARNING) {
         $this->log($lasterror['type'], $lasterror['message'], $lasterror['file'], $lasterror['line']);
     }
     //Put signals to log
     if (!empty($args[0])) {
         $signals = array('SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', 'SIGTRAP', 'SIGABRT', 'SIGBUS', 'SIGFPE', 'SIGKILL', 'SIGSEGV', 'SIGPIPE', 'SIGALRM', 'SIGTERM', 'SIGSTKFLT', 'SIGUSR1', 'SIGUSR2', 'SIGCHLD', 'SIGCONT', 'SIGSTOP', 'SIGTSTP', 'SIGTTIN', 'SIGTTOU', 'SIGURG', 'SIGXCPU', 'SIGXFSZ', 'SIGVTALRM', 'SIGPROF', 'SIGWINCH', 'SIGIO', 'SIGPWR', 'SIGSYS');
         foreach ($signals as $signal) {
             if (defined($signal) && $args[0] === constant($signal)) {
                 $this->log(sprintf(__('Signal "%s" is sent to script!', 'backwpup'), $signal), E_USER_ERROR);
                 break;
             }
         }
     }
     if (function_exists('pcntl_get_last_error')) {
         $error = pcntl_get_last_error();
         if (!empty($error)) {
             $error_msg = pcntl_strerror($error);
             if (!empty($error_msg)) {
                 $error = '(' . $error . ') ' . $error_msg;
             }
         }
         if (!empty($error)) {
             $this->log(sprintf(__('System: %s', 'backwpup'), $error), E_USER_ERROR);
         }
     }
     if (function_exists('posix_get_last_error') && empty($error)) {
         $error = posix_get_last_error();
         if (!empty($error)) {
             $error_msg = posix_strerror($error);
             if (!empty($error_msg)) {
                 $error = '(' . $error . ') ' . $error_msg;
             }
         }
         if (!empty($error)) {
             $this->log(sprintf(__('System: %s', 'backwpup'), $error), E_USER_ERROR);
         }
     }
     $this->do_restart(TRUE);
 }
Ejemplo n.º 15
0
 private function fork()
 {
     for ($i = 0; $i < 3; ++$i) {
         if (isset($pid)) {
             usleep(1000000);
         }
         $pid = pcntl_fork();
         if ($pid >= 0) {
             return $pid;
         }
         $error_number = pcntl_get_last_error();
         $error = "[{$error_number}] " . pcntl_strerror($error_number);
         Logger::getLogger('queue')->warn("Can`t fork, retryNumber={$i}, pid: '" . var_export($pid, true) . "', error: '{$error}'", new Exception());
     }
     throw new RuntimeException('Can`t fork');
 }
Ejemplo n.º 16
0
Archivo: server.php Proyecto: mpyw/co
function signal_handler(int $sig)
{
    if ($sig !== SIGCHLD) {
        return;
    }
    $ignore = NULL;
    while (($rc = pcntl_waitpid(-1, $ignore, WNOHANG)) > 0) {
    }
    if ($rc !== -1 || pcntl_get_last_error() === PCNTL_ECHILD) {
        return;
    }
    fwrite(STDERR, 'waitpid() failed: ' . pcntl_strerror(pcntl_get_last_error()) . "\n");
    exit(1);
}
Ejemplo n.º 17
0
 /**
  * Retrieve the system error message associated with the given errorNo
  *
  * @param int $errorCode
  *
  * @return string
  */
 public function getStringError(int $errorCode)
 {
     return pcntl_strerror($errorCode);
 }
 protected function doFork(InputInterface $input, OutputInterface $output)
 {
     $pid = pcntl_fork();
     if ($pid < 0) {
         $errno = pcntl_get_last_error();
         throw new \RuntimeException("Cannot fork process, error = " . pcntl_strerror($errno));
     } elseif ($pid == 0) {
         // in child process
         $ret = $this->doExecute($input, $output);
         exit(is_numeric($ret) ? $ret : 0);
     } else {
         return $pid;
     }
 }
Ejemplo n.º 19
0
 /**
  * Error logging from pcntl* functions
  *
  * @param string $sMethodCalled
  */
 private function _handlePcntlError($sMethodCalled)
 {
     $nError = pcntl_get_last_error();
     if ($nError == 10) {
         return;
         // ignore: no child processes
     }
     $sErr = pcntl_strerror($nError);
     Logger::getInstance()->crit("ABORT: {$sMethodCalled} error: {$sErr}");
     $this->bRunLoop = FALSE;
 }
Ejemplo n.º 20
0
 /**
  * update the process status
  *
  * @param bool $block
  */
 protected function updateStatus($block = false)
 {
     if ($this->running !== true) {
         return;
     }
     if ($block) {
         $res = pcntl_waitpid($this->pid, $status);
     } else {
         $res = pcntl_waitpid($this->pid, $status, WNOHANG | WUNTRACED);
     }
     if ($res === -1) {
         throw new \RuntimeException('pcntl_waitpid failed. the process maybe available');
     } elseif ($res === 0) {
         $this->running = true;
     } else {
         if (pcntl_wifsignaled($status)) {
             $this->term_signal = pcntl_wtermsig($status);
         }
         if (pcntl_wifstopped($status)) {
             $this->stop_signal = pcntl_wstopsig($status);
         }
         if (pcntl_wifexited($status)) {
             $this->errno = pcntl_wexitstatus($status);
             $this->errmsg = pcntl_strerror($this->errno);
         } else {
             $this->errno = pcntl_get_last_error();
             $this->errmsg = pcntl_strerror($this->errno);
         }
         if (pcntl_wifsignaled($status)) {
             $this->if_signal = true;
         } else {
             $this->if_signal = false;
         }
         $this->running = false;
     }
 }
 protected function waitForBackgroundProcesses()
 {
     //$lastMemory = memory_get_usage(true);
     while (true) {
         //$memory = memory_get_usage(true);
         //if ($memory != $lastMemory) {
         //    echo(
         //        sprintf("memory change: %d, from %d to %d", $memory - $lastMemory, $lastMemory, $memory)
         //        . PHP_EOL
         //    );
         //}
         //$lastMemory = $memory;
         pcntl_signal_dispatch();
         $status = 0;
         $pid = pcntl_waitpid(-1, $status, WNOHANG);
         if ($pid == 0) {
             // no child process has quit
             usleep(200 * 1000);
         } else {
             if ($pid > 0) {
                 // child process with pid = $pid exits
                 $exitStatus = pcntl_wexitstatus($status);
                 $runner = $this->runningProcesses[$pid];
                 if (!$runner instanceof CommandRunner) {
                     throw new \LogicException("Cannot find command runner for process pid = %d", $pid);
                 }
                 unset($this->runningProcesses[$pid]);
                 $runner->onProcessExit($exitStatus, $pid);
                 $newPid = $runner->run();
                 if ($newPid > 0) {
                     $this->runningProcesses[$newPid] = $runner;
                 }
             } else {
                 // error
                 $errno = pcntl_get_last_error();
                 if ($errno == PCNTL_ECHILD) {
                     // all children finished
                     mdebug("No more BackgroundProcessRunner children, continue ...");
                     break;
                 } else {
                     // some other error
                     throw new \RuntimeException("Error waiting for process, error = " . pcntl_strerror($errno));
                 }
             }
         }
     }
 }
 public function fork()
 {
     $sockets = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
     $pid = pcntl_fork();
     $this->isRunning = true;
     if ($pid <= -1) {
         $this->isRunning = false;
         throw new \RuntimeException("Unable to fork child: " . pcntl_strerror(pcntl_get_last_error()));
     } elseif ($pid === 0) {
         //child proc
         try {
             $this->isExternal = true;
             $this->childPid = posix_getpid();
             set_error_handler(array(ThreadConfig::GetErrorHandler(), 'OnUncaughtErrorTriggered'));
             register_shutdown_function(function () {
                 //catch fatal on some cases
                 $fatalErrorCodes = array(E_ERROR, E_COMPILE_ERROR, E_PARSE);
                 $error = error_get_last();
                 if (is_array($error) && isset($error['type']) && in_array($error['type'], $fatalErrorCodes)) {
                     $exception = new SerializableFatalException($error['message'], $error['file'], $error['line'], $error['type']);
                     if ($this->messageInProgress instanceof AsyncMessage) {
                         //mark as error and send back to parent
                         $this->messageInProgress->Error($exception);
                         $this->connection->writeSync($this->messageInProgress);
                     } else {
                         $message = new AsyncMessage(array(), true);
                         $message->setIsOneWay(true);
                         $message->Error($exception);
                         $this->connection->writeSync($message);
                     }
                 }
             });
             $this->loop = $this->loop->afterForkChild();
             fclose($sockets[1]);
             $this->socket = $sockets[0];
             $this->connection = new ThreadConnection($this->loop, $this->socket);
             $this->connection->on('message', function ($connection, AsyncMessage $message) {
                 $this->AttachMessage($message);
             });
             $this->loop->nextTick(function () {
                 $this->messageHandler->InitializeExternal($this);
             });
             $this->loop->run();
         } catch (\Exception $e) {
             $handler = ThreadConfig::GetErrorHandler();
             $result = @$handler->OnUncaughtException($e);
             //redirect exception to client.
             if ($this->messageInProgress instanceof AsyncMessage) {
                 //mark as error and send back to parent
                 $this->messageInProgress->Error($result);
                 $this->connection->writeSync($this->messageInProgress);
             } else {
                 $message = new AsyncMessage(array(), true);
                 $message->setIsOneWay(true);
                 $message->Error($result);
                 $this->connection->writeSync($message);
             }
             //no more chance to handle here :-(
         }
         exit;
     } else {
         // parent
         fclose($sockets[0]);
         $this->socket = $sockets[1];
         $this->getLoop()->afterForkParent();
         $this->connection = new ThreadConnection($this->loop, $this->socket);
         $this->connection->on('message', function ($connection, AsyncMessage $message) {
             $this->AttachMessage($message);
         });
         //keep an eye on the thread
         $this->pidCollector = $this->getLoop()->addPeriodicTimer(5, function (TimerInterface $timer) {
             $this->waitForCompletion($timer);
         });
         $this->childPid = $pid;
     }
 }
Ejemplo n.º 23
0
 /**
  * Retrieve the system error message associated with the given errno
  *
  * @param int $errno
  *
  * @return string
  */
 public function strerror(int $errno) : string
 {
     return pcntl_strerror($errno);
 }
Ejemplo n.º 24
0
 /**
  *
  * Shutdown function is call if script terminates try to make a restart if needed
  *
  * Prepare the job for start
  *
  * @internal param int the signal that terminates the job
  */
 public function shutdown()
 {
     //Put last error to log if one
     $lasterror = error_get_last();
     if ($lasterror['type'] === E_ERROR || $lasterror['type'] === E_PARSE || $lasterror['type'] === E_CORE_ERROR || $lasterror['type'] === E_CORE_WARNING || $lasterror['type'] === E_COMPILE_ERROR || $lasterror['type'] === E_COMPILE_WARNING) {
         $this->log($lasterror['type'], $lasterror['message'], $lasterror['file'], $lasterror['line']);
     }
     $error = false;
     if (function_exists('pcntl_get_last_error')) {
         $error = pcntl_get_last_error();
         if (!empty($error)) {
             $error_msg = pcntl_strerror($error);
             if (!empty($error_msg)) {
                 $error = '(' . $error . ') ' . $error_msg;
             }
         }
         if (!empty($error)) {
             $this->log(sprintf(__('System: %s', 'backwpup'), $error), E_USER_ERROR);
         }
     }
     if (function_exists('posix_get_last_error') && !$error) {
         $error = posix_get_last_error();
         if (!empty($error)) {
             $error_msg = posix_strerror($error);
             if (!empty($error_msg)) {
                 $error = '(' . $error . ') ' . $error_msg;
             }
         }
         if (!empty($error)) {
             $this->log(sprintf(__('System: %s', 'backwpup'), $error), E_USER_ERROR);
         }
     }
     $this->do_restart(true);
 }
Ejemplo n.º 25
0
 /**
  * Do child cleanup if child exited and mark for restart on error
  *
  * @param array $signalInfo Returned from pcntl_sigtimedwait()
  */
 protected function cleanupChild(array $signalInfo, $forceFinished = false)
 {
     if ($signalInfo['signo'] !== SIGCHLD) {
         throw new \InvalidArgumentException('Can only cleanup children on SIGCHLD event.');
     }
     if (!isset($this->processPIDs[$signalInfo['pid']])) {
         throw new \InvalidArgumentException('Received SIGCHLD signal from unknown process "' . $signalInfo['pid'] . '"');
     }
     $name = $this->processPIDs[$signalInfo['pid']];
     // Cleanup child process
     $childStatus = null;
     if (($childPid = \pcntl_waitpid($signalInfo['pid'], $childStatus)) === -1) {
         $errno = \pcntl_get_last_error();
         $error = \pcntl_strerror($errno);
         throw new \RuntimeException('Failed to collect child "' . $signalInfo['pid'] . '": (' . $errno . ') ' . $error);
     }
     unset($this->processPIDs[$signalInfo['pid']]);
     $this->processStarted[$name] = 0;
     // Abort on normal exit (status: 0)
     if ($forceFinished || \pcntl_wifexited($childStatus) && \pcntl_wexitstatus($childStatus) === 0) {
         $this->processFinished[$name] = \microtime(true);
         unset($this->processRestart[$name]);
     } else {
         $this->processRestart[$name] = \microtime(true) + (isset($this->processTimeouts[$name]) ? $this->processTimeouts[$name] : 0);
     }
 }