60 private const RESTART_ON_ERROR = 1;
68 throw new RuntimeException(
"MediaWiki\Maintenance\ForkController cannot be used from the web." );
69 } elseif ( !extension_loaded(
'pcntl' ) ) {
70 throw new RuntimeException(
71 'MediaWiki\Maintenance\ForkController requires pcntl extension to be installed.'
73 } elseif ( !extension_loaded(
'posix' ) ) {
74 throw new RuntimeException(
75 'MediaWiki\Maintenance\ForkController requires posix extension to be installed.'
78 $this->procsToStart = $numProcs;
82 self::$RESTARTABLE_SIGNALS = [
83 SIGFPE, SIGILL, SIGSEGV, SIGBUS,
84 SIGABRT, SIGSYS, SIGPIPE, SIGXCPU, SIGXFSZ,
101 pcntl_signal( SIGTERM, [ $this,
'handleTermSignal' ],
false );
105 if ( $this->procsToStart ) {
106 if ( $this->
forkWorkers( $this->procsToStart ) ==
'child' ) {
109 $this->procsToStart = 0;
114 $deadPid = pcntl_wait( $status );
116 if ( $deadPid > 0 ) {
118 unset( $this->children[$deadPid] );
119 if ( $this->flags & self::RESTART_ON_ERROR ) {
120 if ( pcntl_wifsignaled( $status ) ) {
123 $signal = pcntl_wtermsig( $status );
124 if ( in_array( $signal, self::$RESTARTABLE_SIGNALS ) ) {
125 echo
"Worker exited with signal $signal, restarting\n";
126 $this->procsToStart++;
128 } elseif ( pcntl_wifexited( $status ) ) {
130 $exitStatus = pcntl_wexitstatus( $status );
131 if ( $exitStatus != 0 ) {
132 echo
"Worker exited with status $exitStatus, restarting\n";
133 $this->procsToStart++;
135 echo
"Worker exited normally\n";
140 if ( $this->procsToStart ) {
146 if ( function_exists(
'pcntl_signal_dispatch' ) ) {
147 pcntl_signal_dispatch();
155 if ( $this->termReceived ) {
156 foreach ( $this->children as $childPid => $unused ) {
157 posix_kill( $childPid, SIGTERM );
159 $this->termReceived =
false;
161 }
while ( count( $this->children ) );
162 pcntl_signal( SIGTERM, SIG_DFL );
193 for ( $i = 0; $i < $numProcs; $i++ ) {
197 echo
"Error creating child processes\n";
203 $this->childNumber = $i;
207 $this->children[$pid] =
true;
215 $this->children =
null;
216 pcntl_signal( SIGTERM, SIG_DFL );
220 $this->termReceived =
true;
227 class_alias( ForkController::class,
'ForkController' );
wfIsCLI()
Check if we are running from the commandline.
Manage forking inside CLI maintenance scripts.
start()
Start the child processes.
getChildNumber()
Get the number of the child currently running.
__construct( $numProcs, $flags=0)
forkWorkers( $numProcs)
Fork a number of worker processes.
static $RESTARTABLE_SIGNALS
handleTermSignal( $signal)
Functions to get cache objects.
static clear()
Clear all the cached instances.
Helper class to manage Redis connections.
static destroySingletons()
Destroy all singleton() instances.