Merge "Set ignore_user_abort( true ) during DB commit for sanity"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 28 Sep 2016 03:27:58 +0000 (03:27 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 28 Sep 2016 03:27:58 +0000 (03:27 +0000)
1  2 
includes/libs/rdbms/loadbalancer/LoadBalancer.php

@@@ -1024,7 -1024,7 +1024,7 @@@ class LoadBalancer implements ILoadBala
        }
  
        public function finalizeMasterChanges() {
 -              $this->forEachOpenMasterConnection( function ( DatabaseBase $conn ) {
 +              $this->forEachOpenMasterConnection( function ( Database $conn ) {
                        // Any error should cause all DB transactions to be rolled back together
                        $conn->setTrxEndCallbackSuppression( false );
                        $conn->runOnTransactionPreCommitCallbacks();
  
                $failures = [];
                $this->forEachOpenMasterConnection(
 -                      function ( DatabaseBase $conn ) use ( $fname, &$failures ) {
 +                      function ( Database $conn ) use ( $fname, &$failures ) {
                                $conn->setTrxEndCallbackSuppression( true );
                                try {
                                        $conn->flushSnapshot( $fname );
        public function commitMasterChanges( $fname = __METHOD__ ) {
                $failures = [];
  
+               /** @noinspection PhpUnusedLocalVariableInspection */
+               $scope = $this->getScopedPHPBehaviorForCommit(); // try to ignore client aborts
                $restore = ( $this->trxRoundId !== false );
                $this->trxRoundId = false;
                $this->forEachOpenMasterConnection(
  
        public function runMasterPostTrxCallbacks( $type ) {
                $e = null; // first exception
 -              $this->forEachOpenMasterConnection( function ( DatabaseBase $conn ) use ( $type, &$e ) {
 +              $this->forEachOpenMasterConnection( function ( Database $conn ) use ( $type, &$e ) {
                        $conn->setTrxEndCallbackSuppression( false );
                        if ( $conn->writesOrCallbacksPending() ) {
                                // This happens if onTransactionIdle() callbacks leave callbacks on *another* DB
        }
  
        public function suppressTransactionEndCallbacks() {
 -              $this->forEachOpenMasterConnection( function ( DatabaseBase $conn ) {
 +              $this->forEachOpenMasterConnection( function ( Database $conn ) {
                        $conn->setTrxEndCallbackSuppression( true );
                } );
        }
                } );
        }
  
+       /**
+        * Make PHP ignore user aborts/disconnects until the returned
+        * value leaves scope. This returns null and does nothing in CLI mode.
+        *
+        * @return ScopedCallback|null
+        */
+       final protected function getScopedPHPBehaviorForCommit() {
+               if ( PHP_SAPI != 'cli' ) { // http://bugs.php.net/bug.php?id=47540
+                       $old = ignore_user_abort( true ); // avoid half-finished operations
+                       return new ScopedCallback( function () use ( $old ) {
+                               ignore_user_abort( $old );
+                       } );
+               }
+               return null;
+       }
        function __destruct() {
                // Avoid connection leaks for sanity
                $this->closeAll();