View Issue Details

IDProjectCategoryView StatusLast Update
0007286OXID eShop (all versions)4.07. Source code, Testpublic2021-11-12 09:19
ReporterSteven 
PrioritylowSeverityminorReproducibilityalways
Status acknowledgedResolutionopen 
Product Version6.3.1 
Target VersionFixed in Version 
Summary0007286: Logger Service's fallback in case of corrupted DI Container uses DI Container again
DescriptionFirst of all: This issue was discovered investigating another possible issue linked to the container_cache.php file. Therefore the issue is described according this exact usecase. However it is not known in which situation this also might happen. The main issue is a fallback, which does not function as a real fallback, since it uses the ContainerFactory again, which actually is the main reason to fail in the first place and obviously leads to start the fallback. In short: If A fails, let's use B...which uses A.

If your source/tmp/container_cache.php file exists, but is corrupted (e.g. empty), the OXID framework runs into an error while trying to retrieve a service from the container. The framework correctly wants to write an exception into the logfile by calling

OxidEsales\EshopCommunity\Core\Exception\ExceptionHandler::handleUncaughtException

To do so, the framework first tries to initialize the LoggerService via the ContainerFactory, which results in an exception again, since the container_cache is still broken. However, this exception is also catched correctly. Then the frameworks wants to initialize the Logger without the DI Container - or at least that's what it states:

/**
    * Its not possible to get the logger from the DI container.
    * Try again to log original exception (without DI container) in order to show the root cause of a problem.
    */
try {
    $loggerServiceFactory = new LoggerServiceFactory(new Context(Registry::getConfig()));
    $logger = $loggerServiceFactory->getLogger();
    $logger->error($this->getFormattedException($exception));
} catch (\Throwable $throwableWithoutPossibilityToWriteToLogFile) {
    // It is not possible to log because e.g. the log file is not writable.
}

This time

$logger = $loggerServiceFactory->getLogger();

is used, which later tries to establish a database connection via the method

OxidEsales\EshopCommunity\Core\Database\Adapter\Doctrine\Database::connect

This connect method needs to get the connection configuration, which brings us to the method

OxidEsales\EshopCommunity\Core\Database\Adapter\Doctrine\Database::getConnectionConfiguration

which then calls

OxidEsales\EshopCommunity\Core\Database\Adapter\Doctrine\Database::configureSqlLogger

private function configureSqlLogger(Configuration $configuration): void
{
    $container = ContainerFactory::getInstance()->getContainer();
    /** logger instantiation requires auto-wiring(compiled container) */
    if ($container->isCompiled()) {
        $databaseLogger = $container->get(DatabaseLoggerFactoryInterface::class)->getDatabaseLogger();
        $configuration->setSQLLogger($databaseLogger);
    }
}

As you can see, it uses the ContainerFactory on first line and therefore runs into an error the third time. The logger (obviously) can't be initialized with the "fallback" and the exception is not written to the log.
Steps To Reproduce- Open the file source/tmp/container_cache.php.
- Corrupt the file by emptying it. Do not delete it completely.
- Open your shop in your webbrowser.
- You will see a maintenance mode, but there is no entry in your logfile.

The exception "ProjectServiceContainer not found" was thrown, but not written. You can follow the path like described above with a debugger.
TagsCache, Log, Service
ThemeNot defined
BrowserNot defined
PHP VersionNot defined
Database VersionNot defined

Activities

QA

2021-11-12 09:19

administrator   ~0013501

-MK