}
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();