58 throw new MWException(
"ForkController cannot be used from the web." );
60 $this->procsToStart = $numProcs;
77 pcntl_signal( SIGTERM, [ $this,
'handleTermSignal' ],
false );
81 if ( $this->procsToStart ) {
82 if ( $this->
forkWorkers( $this->procsToStart ) ==
'child' ) {
85 $this->procsToStart = 0;
90 $deadPid = pcntl_wait(
$status );
94 unset( $this->children[$deadPid] );
95 if ( $this->flags & self::RESTART_ON_ERROR ) {
96 if ( pcntl_wifsignaled(
$status ) ) {
99 $signal = pcntl_wtermsig(
$status );
100 if ( in_array( $signal, self::$restartableSignals ) ) {
101 echo
"Worker exited with signal $signal, restarting\n";
102 $this->procsToStart++;
104 } elseif ( pcntl_wifexited(
$status ) ) {
106 $exitStatus = pcntl_wexitstatus(
$status );
107 if ( $exitStatus != 0 ) {
108 echo
"Worker exited with status $exitStatus, restarting\n";
109 $this->procsToStart++;
111 echo
"Worker exited normally\n";
116 if ( $this->procsToStart ) {
122 if ( function_exists(
'pcntl_signal_dispatch' ) ) {
123 pcntl_signal_dispatch();
125 declare( ticks = 1 ) {
131 if ( $this->termReceived ) {
132 foreach ( $this->children as $childPid => $unused ) {
133 posix_kill( $childPid, SIGTERM );
135 $this->termReceived =
false;
137 }
while ( count( $this->children ) );
138 pcntl_signal( SIGTERM, SIG_DFL );
155 MediaWikiServices::resetChildProcessServices();
173 for ( $i = 0; $i < $numProcs; $i++ ) {
176 if ( $pid === -1 || $pid ===
false ) {
177 echo
"Error creating child processes\n";
183 $this->childNumber = $i;
187 $this->children[$pid] =
true;
197 $this->children =
null;
198 pcntl_signal( SIGTERM, SIG_DFL );
202 $this->termReceived =
true;