Skip to content

Commit ed959fb

Browse files
committed
Avoid race conditions when configuring the SQLite database
1 parent 23331b3 commit ed959fb

File tree

1 file changed

+32
-4
lines changed

1 file changed

+32
-4
lines changed

Diff for: wp-includes/sqlite-ast/class-wp-sqlite-configurator.php

+32-4
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,20 @@ public function __construct(
5757
* driver version, and if it is not, it will configure the database.
5858
*/
5959
public function ensure_database_configured(): void {
60-
$version = SQLITE_DRIVER_VERSION;
61-
$db_version = $this->driver->get_saved_driver_version();
62-
if ( version_compare( $version, $db_version ) > 0 ) {
63-
$this->configure_database();
60+
// Use an EXCLUSIVE transaction to prevent multiple connections
61+
// from attempting to configure the database at the same time.
62+
$this->driver->execute_sqlite_query( 'BEGIN EXCLUSIVE TRANSACTION' );
63+
try {
64+
$version = SQLITE_DRIVER_VERSION;
65+
$db_version = $this->driver->get_saved_driver_version();
66+
if ( version_compare( $version, $db_version ) > 0 ) {
67+
$this->run_database_configuration();
68+
}
69+
} catch ( Throwable $e ) {
70+
$this->driver->execute_sqlite_query( 'ROLLBACK' );
71+
throw $e;
6472
}
73+
$this->driver->execute_sqlite_query( 'COMMIT' );
6574
}
6675

6776
/**
@@ -73,6 +82,25 @@ public function ensure_database_configured(): void {
7382
* SQLite driver version and attempt to repair any configuration corruption.
7483
*/
7584
public function configure_database(): void {
85+
// Use an EXCLUSIVE transaction to prevent multiple connections
86+
// from attempting to configure the database at the same time.
87+
$this->driver->execute_sqlite_query( 'BEGIN EXCLUSIVE TRANSACTION' );
88+
try {
89+
$this->run_database_configuration();
90+
} catch ( Throwable $e ) {
91+
$this->driver->execute_sqlite_query( 'ROLLBACK' );
92+
throw $e;
93+
}
94+
$this->driver->execute_sqlite_query( 'COMMIT' );
95+
}
96+
97+
/**
98+
* Run the SQLite database configuration.
99+
*
100+
* This method executes the database configuration steps, ensuring that all
101+
* tables required for MySQL emulation in SQLite are created and populated.
102+
*/
103+
private function run_database_configuration(): void {
76104
$this->ensure_global_variables_table();
77105
$this->information_schema_builder->ensure_information_schema_tables();
78106
$this->information_schema_reconstructor->ensure_correct_information_schema();

0 commit comments

Comments
 (0)