diff options
author | jenkins-bot <jenkins-bot@gerrit.wikimedia.org> | 2025-04-07 11:38:35 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@wikimedia.org> | 2025-04-07 11:38:35 +0000 |
commit | 88aef6c1421f3543c67c8ee923386971d6e4ece6 (patch) | |
tree | 66678dead7bcf6f75d9939e7a5924724dfb6a217 /includes | |
parent | b53bd618cc8a8fc18f5b1c04b56eb6c4941d1fd1 (diff) | |
parent | 2b65587e4d92e7f27661e8821b14f74ade939cfa (diff) | |
download | mediawikicore-88aef6c1421f3543c67c8ee923386971d6e4ece6.tar.gz mediawikicore-88aef6c1421f3543c67c8ee923386971d6e4ece6.zip |
Merge "block: Fix DBS::acquireTarget() race using GET_LOCK()"
Diffstat (limited to 'includes')
-rw-r--r-- | includes/api/ApiMessageTrait.php | 1 | ||||
-rw-r--r-- | includes/block/DatabaseBlockStore.php | 13 |
2 files changed, 14 insertions, 0 deletions
diff --git a/includes/api/ApiMessageTrait.php b/includes/api/ApiMessageTrait.php index 8f796101ce2b..9c2bd7575117 100644 --- a/includes/api/ApiMessageTrait.php +++ b/includes/api/ApiMessageTrait.php @@ -67,6 +67,7 @@ trait ApiMessageTrait { 'importuploaderrorpartial' => 'partialupload', 'importuploaderrorsize' => 'filetoobig', 'importuploaderrortemp' => 'notempdir', + 'ipb-block-not-found' => 'alreadyblocked', 'ipb_already_blocked' => 'alreadyblocked', 'ipb_blocked_as_range' => 'blockedasrange', 'ipb_cant_unblock' => 'cantunblock', diff --git a/includes/block/DatabaseBlockStore.php b/includes/block/DatabaseBlockStore.php index c33157b58157..20f662e044d5 100644 --- a/includes/block/DatabaseBlockStore.php +++ b/includes/block/DatabaseBlockStore.php @@ -1044,6 +1044,7 @@ class DatabaseBlockStore { $targetUserName = (string)$target; $targetUserId = $target->getUserIdentity()->getId( $this->wikiId ); $targetConds = [ 'bt_user' => $targetUserId ]; + $targetLockKey = $dbw->getDomainID() . ':block:u:' . $targetUserId; } else { $targetAddress = (string)$target; $targetUserName = null; @@ -1052,6 +1053,8 @@ class DatabaseBlockStore { 'bt_address' => $targetAddress, 'bt_auto' => $isAuto, ]; + $targetLockKey = $dbw->getDomainID() . ':block:' . + ( $isAuto ? 'a' : 'i' ) . ':' . $targetAddress; } $condsWithCount = $targetConds; @@ -1059,6 +1062,15 @@ class DatabaseBlockStore { $condsWithCount['bt_count'] = $expectedTargetCount; } + $dbw->lock( $targetLockKey, __METHOD__ ); + $func = __METHOD__; + $dbw->onTransactionCommitOrIdle( + static function () use ( $dbw, $targetLockKey, $func ) { + $dbw->unlock( $targetLockKey, "$func.closure" ); + }, + __METHOD__ + ); + // This query locks the index gap when the target doesn't exist yet, // so there is a risk of throttling adjacent block insertions, // especially on small wikis which have larger gaps. If this proves to @@ -1076,6 +1088,7 @@ class DatabaseBlockStore { ->select( [ 'bt_id', 'bt_count' ] ) ->from( 'block_target' ) ->where( $targetConds ) + ->forUpdate() ->caller( __METHOD__ ) ->fetchResultSet(); if ( $res->numRows() > 1 ) { |