Merge pull request #9456 from open-sausages/pulls/4/avoid-tempdatabase-infinite-loop

BUG Infinite loops in TempDatabase (fixes #8902)
This commit is contained in:
Loz Calver 2020-04-09 09:28:57 +01:00 committed by GitHub
commit 3ad4b93daa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -24,6 +24,13 @@ class TempDatabase
*/ */
protected $name = null; protected $name = null;
/**
* Workaround to avoid infinite loops.
*
* @var Exception
*/
private $skippedException = null;
/** /**
* Optionally remove the test DB when the PHP process exits * Optionally remove the test DB when the PHP process exits
* *
@ -232,9 +239,13 @@ class TempDatabase
$dataClasses = ClassInfo::subclassesFor(DataObject::class); $dataClasses = ClassInfo::subclassesFor(DataObject::class);
array_shift($dataClasses); array_shift($dataClasses);
$oldCheckAndRepairOnBuild = Config::inst()->get(DBSchemaManager::class, 'check_and_repair_on_build');
Config::modify()->set(DBSchemaManager::class, 'check_and_repair_on_build', false);
$schema = $this->getConn()->getSchemaManager(); $schema = $this->getConn()->getSchemaManager();
$schema->quiet(); $schema->quiet();
$schema->schemaUpdate(function () use ($dataClasses, $extraDataObjects) { $schema->schemaUpdate(
function () use ($dataClasses, $extraDataObjects) {
foreach ($dataClasses as $dataClass) { foreach ($dataClasses as $dataClass) {
// Check if class exists before trying to instantiate - this sidesteps any manifest weirdness // Check if class exists before trying to instantiate - this sidesteps any manifest weirdness
if (class_exists($dataClass)) { if (class_exists($dataClass)) {
@ -254,7 +265,10 @@ class TempDatabase
} }
} }
} }
}); }
);
Config::modify()->set(DBSchemaManager::class, 'check_and_repair_on_build', $oldCheckAndRepairOnBuild);
ClassInfo::reset_db_cache(); ClassInfo::reset_db_cache();
DataObject::singleton()->flushCache(); DataObject::singleton()->flushCache();
@ -293,6 +307,13 @@ class TempDatabase
try { try {
$this->rebuildTables($extraDataObjects); $this->rebuildTables($extraDataObjects);
} catch (DatabaseException $ex) { } catch (DatabaseException $ex) {
// Avoid infinite loops
if ($this->skippedException && $this->skippedException->getMessage() == $ex->getMessage()) {
throw $ex;
}
$this->skippedException = $ex;
// In case of error during build force a hard reset // In case of error during build force a hard reset
// e.g. pgsql doesn't allow schema updates inside transactions // e.g. pgsql doesn't allow schema updates inside transactions
$this->kill(); $this->kill();