[BUGFIX] Exception in Locker if typo3temp does not exist 82/28482/10
authorAlexander Opitz <opitz.alexander@googlemail.com>
Tue, 18 Mar 2014 11:15:05 +0000 (12:15 +0100)
committerMarkus Klein <klein.t3@mfc-linz.at>
Tue, 18 Mar 2014 20:20:27 +0000 (21:20 +0100)
Follow-up to 2268f64c18b607ba39d06b1580afb0ccd786d6b1

If typo3temp does not exist, the Locker should throw an exception.
The ClassLoader needs to catch this exception and acts upon
depending on whether we are in the Installer or not.

When in the Installer, locking has to be skipped completely due to
missing typo3temp directory.

Resolves: #57008
Releases: 6.2
Change-Id: Ic595dc97826cd94d6f173b7c681194ed754ed3e0
Reviewed-on: https://review.typo3.org/28482
Reviewed-by: Christian Kuhn
Tested-by: Christian Kuhn
Reviewed-by: Markus Klein
Tested-by: Markus Klein
typo3/sysext/core/Classes/Core/ClassLoader.php
typo3/sysext/core/Classes/Locking/Locker.php

index 8791529..316c47c 100644 (file)
@@ -698,6 +698,12 @@ class ClassLoader {
                if (!$this->isLoadingLocker) {
                        $lockObject = $this->getLocker();
 
+                       if ($lockObject === NULL) {
+                               // During installation typo3temp does not yet exist, so the locker can not
+                               // do its job. In this case it does not need to be released again.
+                               return FALSE;
+                       }
+
                        // We didn't lock yet so do it
                        if (!$lockObject->getLockStatus()) {
                                if (!$lockObject->acquireExclusiveLock()) {
@@ -726,12 +732,29 @@ class ClassLoader {
        /**
         * Gets the TYPO3 Locker object or creates an instance of it.
         *
-        * @return \TYPO3\CMS\Core\Locking\Locker
+        * @throws \RuntimeException
+        * @return \TYPO3\CMS\Core\Locking\Locker|NULL Only NULL if we are in installer and typo3temp does not exist yet
         */
        protected function getLocker() {
                if (NULL === $this->lockObject) {
                        $this->isLoadingLocker = TRUE;
-                       $this->lockObject = new Locker('ClassLoader-cache-classes', Locker::LOCKING_METHOD_SIMPLE);
+
+                       try {
+                               $this->lockObject = new Locker('ClassLoader-cache-classes', Locker::LOCKING_METHOD_SIMPLE);
+                       } catch (\RuntimeException $e) {
+                               // The RuntimeException in constructor happens if directory typo3temp/locks could not be created.
+                               // This usually happens during installation step 1 where typo3temp itself does not exist yet. In
+                               // this case we proceed without locking, otherwise a missing typo3temp directory indicates a
+                               // hard problem of the instance and we throw up.
+                               // @TODO: This solution currently conflicts with separation of concerns since the class loader
+                               // handles installation specific stuff. Find a better way to do this.
+                               if (defined('TYPO3_enterInstallScript') && TYPO3_enterInstallScript) {
+                                       // Installer is running => So work without Locking.
+                                       return NULL;
+                               } else {
+                                       throw $e;
+                               }
+                       }
                        $this->lockObject->setEnableLogging(FALSE);
                        $this->isLoadingLocker = FALSE;
                }
index 74f304a..e310926 100644 (file)
@@ -123,12 +123,8 @@ class Locker {
                        case self::LOCKING_METHOD_SIMPLE:
                                // intended fall through
                        case self::LOCKING_METHOD_FLOCK:
-                               $path = PATH_site . self::FILE_LOCK_FOLDER;
-                               if (!is_dir($path)) {
-                                       GeneralUtility::mkdir($path);
-                               }
                                $this->id = md5($id);
-                               $this->resource = $path . $this->id;
+                               $this->createPathIfNeeded();
                                break;
                        case self::LOCKING_METHOD_SEMAPHORE:
                                $this->id = abs(crc32($id));
@@ -486,4 +482,24 @@ class Locker {
                }
        }
 
+       /**
+        * Tests if the directory for simple locks is available.
+        * If not, the directory will be created. The lock path is usually
+        * below typo3temp, typo3temp itself should exist already
+        *
+        * @return void
+        * @throws \RuntimeException If path couldn't be created.
+        */
+       protected function createPathIfNeeded() {
+               $path = PATH_site . self::FILE_LOCK_FOLDER;
+               if (!is_dir($path)) {
+                       // Not using mkdir_deep on purpose here, if typo3temp itself
+                       // does not exist, this issue should be solved on a different
+                       // level of the application.
+                       if (!GeneralUtility::mkdir($path)) {
+                               throw new \RuntimeException('Cannot create directory ' . $path, 1395140007);
+                       }
+               }
+               $this->resource = $path . $this->id;
+       }
 }