Use mediawiki/at-ease library for suppressing warnings
[lhc/web/wiklou.git] / includes / MediaWiki.php
index b1d0738..7a0d7b7 100644 (file)
@@ -114,7 +114,7 @@ class MediaWiki {
                        // If we get here, we definitely don't have a valid title; throw an exception.
                        // Try to get detailed invalid title exception first, fall back to MalformedTitleException.
                        Title::newFromTextThrow( $title );
-                       throw new MalformedTitleException( null, $title );
+                       throw new MalformedTitleException( 'badtitletext', $title );
                }
 
                return $ret;
@@ -422,8 +422,7 @@ class MediaWiki {
        }
 
        /**
-        * Run the current MediaWiki instance
-        * index.php just calls this
+        * Run the current MediaWiki instance; index.php just calls this
         */
        public function run() {
                try {
@@ -434,16 +433,68 @@ class MediaWiki {
                                // Bug 62091: while exceptions are convenient to bubble up GUI errors,
                                // they are not internal application faults. As with normal requests, this
                                // should commit, print the output, do deferred updates, jobs, and profiling.
-                               wfGetLBFactory()->commitMasterChanges();
+                               $this->doPreOutputCommit();
                                $e->report(); // display the GUI error
                        }
+               } catch ( Exception $e ) {
+                       MWExceptionHandler::handleException( $e );
+               }
+
+               $this->doPostOutputShutdown( 'normal' );
+       }
+
+       /**
+        * This function commits all DB changes as needed before
+        * the user can receive a response (in case commit fails)
+        *
+        * @since 1.26
+        */
+       public function doPreOutputCommit() {
+               // Either all DBs should commit or none
+               ignore_user_abort( true );
+               wfGetLBFactory()->commitMasterChanges();
+       }
+
+       /**
+        * This function does work that can be done *after* the
+        * user gets the HTTP response so they don't block on it
+        *
+        * @param string $mode Use 'fast' to always skip job running
+        * @since 1.26
+        */
+       public function doPostOutputShutdown( $mode = 'normal' ) {
+               // Show profiling data if enabled
+               Profiler::instance()->logDataPageOutputOnly();
+
+               $that = $this;
+               $callback = function () use ( $that, $mode ) {
+                       try {
+                               // Assure deferred updates are not in the main transaction
+                               wfGetLBFactory()->commitMasterChanges();
+                               // Run jobs occasionally, if enabled
+                               if ( $mode === 'normal' ) {
+                                       $that->triggerJobs();
+                               }
+                               // Do deferred updates and job insertion and final commit
+                               $that->restInPeace();
+                       } catch ( Exception $e ) {
+                               MWExceptionHandler::handleException( $e );
+                       }
+               };
+
+               if ( function_exists( 'register_postsend_function' ) ) {
+                       // https://github.com/facebook/hhvm/issues/1230
+                       register_postsend_function( $callback );
+               } else {
                        if ( function_exists( 'fastcgi_finish_request' ) ) {
                                fastcgi_finish_request();
+                       } else {
+                               // Either all DB and deferred updates should happen or none.
+                               // The later should not be cancelled due to client disconnect.
+                               ignore_user_abort( true );
                        }
-                       $this->triggerJobs();
-                       $this->restInPeace();
-               } catch ( Exception $e ) {
-                       MWExceptionHandler::handleException( $e );
+
+                       $callback();
                }
        }
 
@@ -458,7 +509,7 @@ class MediaWiki {
                        list( $host, $lag ) = wfGetLB()->getMaxLag();
                        if ( $lag > $maxLag ) {
                                $resp = $this->context->getRequest()->response();
-                               $resp->header( 'HTTP/1.1 503 Service Unavailable' );
+                               $resp->statusHeader( 503 );
                                $resp->header( 'Retry-After: ' . max( intval( $maxLag ), 5 ) );
                                $resp->header( 'X-Database-Lag: ' . intval( $lag ) );
                                $resp->header( 'Content-Type: text/plain' );
@@ -582,16 +633,13 @@ class MediaWiki {
                // Actually do the work of the request and build up any output
                $this->performRequest();
 
-               // Either all DB and deferred updates should happen or none.
-               // The later should not be cancelled due to client disconnect.
-               ignore_user_abort( true );
                // Now commit any transactions, so that unreported errors after
-               // output() don't roll back the whole DB transaction
-               wfGetLBFactory()->commitMasterChanges();
+               // output() don't roll back the whole DB transaction and so that
+               // we avoid having both success and error text in the response
+               $this->doPreOutputCommit();
 
                // Output everything!
                $this->context->getOutput()->output();
-
        }
 
        /**
@@ -605,6 +653,9 @@ class MediaWiki {
                // Do any deferred jobs
                DeferredUpdates::doUpdates( 'commit' );
 
+               // Make sure any lazy jobs are pushed
+               JobQueueGroup::pushLazyJobs();
+
                // Log profiling data, e.g. in the database or UDP
                wfLogProfilingData();
 
@@ -621,7 +672,7 @@ class MediaWiki {
         * to run a specified number of jobs. This registers a callback to cleanup
         * the socket once it's done.
         */
-       protected function triggerJobs() {
+       public function triggerJobs() {
                $jobRunRate = $this->config->get( 'JobRunRate' );
                if ( $jobRunRate <= 0 || wfReadOnly() ) {
                        return;
@@ -664,7 +715,7 @@ class MediaWiki {
 
                $errno = $errstr = null;
                $info = wfParseUrl( $this->config->get( 'Server' ) );
-               wfSuppressWarnings();
+               MediaWiki\suppressWarnings();
                $sock = fsockopen(
                        $info['host'],
                        isset( $info['port'] ) ? $info['port'] : 80,
@@ -674,7 +725,7 @@ class MediaWiki {
                        // is a problem elsewhere.
                        0.1
                );
-               wfRestoreWarnings();
+               MediaWiki\restoreWarnings();
                if ( !$sock ) {
                        $runJobsLogger->error( "Failed to start cron API (socket error $errno): $errstr" );
                        // Fall back to running the job here while the user waits