[FOLLOWUP][BUGFIX] Reestablish DB connection in long-running tasks 93/42893/9
authorMarkus Klein <markus.klein@typo3.org>
Thu, 27 Aug 2015 17:07:04 +0000 (19:07 +0200)
committerMarkus Klein <markus.klein@typo3.org>
Mon, 7 Sep 2015 18:25:41 +0000 (20:25 +0200)
Reconnecting in isConnected() is not necessary as the next query() will
check the status and reconnect properly if required. Using ping() does
not work with mysqlnd - only if mysqli.reconnect=1 is set. Setting this
is bad practice since a ping() would only reconnect but not properly
reinitialize the charset etc.

Thus a check in Install Tool is added to make sure mysqli.reconnect is
set to "0".

Resolves: #69001
Resolves: #69289
Releases: master, 6.2
Change-Id: I3c2cac91e96fdee8bff113f848341856ec51829b
Reviewed-on: http://review.typo3.org/42893
Reviewed-by: Stephan GroƟberndt <stephan@grossberndt.de>
Reviewed-by: Alexander Opitz <opitz.alexander@googlemail.com>
Tested-by: Alexander Opitz <opitz.alexander@googlemail.com>
Reviewed-by: Helmut Hummel <helmut.hummel@typo3.org>
Tested-by: Helmut Hummel <helmut.hummel@typo3.org>
Reviewed-by: Markus Klein <markus.klein@typo3.org>
Tested-by: Markus Klein <markus.klein@typo3.org>
typo3/sysext/core/Classes/Core/SystemEnvironmentBuilder.php
typo3/sysext/core/Classes/Database/DatabaseConnection.php
typo3/sysext/install/Classes/SystemEnvironment/Check.php
typo3/sysext/scheduler/Classes/Controller/SchedulerModuleController.php

index 5bc25d8..a0a33b0 100644 (file)
@@ -1570,10 +1570,8 @@ class DatabaseConnection {
                // We think we're still connected
                if ($this->isConnected) {
                        // Check if this is really the case or if the database server has gone away for some reason
+                       // Using mysqlnd ping() does not reconnect (which we would not want anyway since charset etc would not be reinitialized that way)
                        $this->isConnected = $this->link->ping();
-                       if (!$this->isConnected) {
-                               $this->connectDB();
-                       }
                }
                return $this->isConnected;
        }
index 0719b94..9a49be6 100644 (file)
@@ -85,6 +85,7 @@ class Check {
                $statusArray[] = $this->checkMaxExecutionTime();
                $statusArray[] = $this->checkDisableFunctions();
                $statusArray[] = $this->checkDownloadsPossible();
+               $statusArray[] = $this->checkMysqliReconnectSetting();
                $statusArray[] = $this->checkAlwaysPopulateRawPostDataSetting();
                $statusArray[] = $this->checkDocRoot();
                $statusArray[] = $this->checkOpenBaseDir();
@@ -473,7 +474,31 @@ class Check {
        }
 
        /**
-        * Check that always_populate_raw_post_data has been set to -1 on PHP between 5.6 and 7.0
+        * Verify that mysqli.reconnect is set to 0 in order to avoid improper reconnects
+        *
+        * @return Status\StatusInterface
+        */
+       protected function checkMysqliReconnectSetting() {
+
+               $currentMysqliReconnectSetting = ini_get('mysqli.reconnect');
+               if ($currentMysqliReconnectSetting === '1') {
+                       $status = new Status\ErrorStatus();
+                       $status->setTitle('PHP mysqli.reconnect is enabled');
+                       $status->setMessage(
+                               'mysqli.reconnect=1' . LF .
+                               'PHP is configured to automatically reconnect the database connection on disconnection.' . LF .
+                               ' Warning: If (e.g. during a long-running task) the connection is dropped and automatically reconnected, ' .
+                               ' it may not be reinitialized properly (e.g. charset) and write mangled data to the database!'
+                       );
+               } else {
+                       $status = new Status\OkStatus();
+                       $status->setTitle('PHP mysqli.reconnect is fine');
+               }
+               return $status;
+       }
+
+       /**
+        * Check that always_populate_raw_post_data has been set to -1 on PHP 5.6 or newer
         *
         * @return Status\StatusInterface
         */
index a5f996b..a45a157 100644 (file)
@@ -1087,7 +1087,7 @@ class SchedulerModuleController extends \TYPO3\CMS\Backend\Module\BaseScriptClas
 
                                                // Check if the last run failed
                                                if (!empty($schedulerRecord['lastexecution_failure'])) {
-                                                       // Try to get the stored exception object
+                                                       // Try to get the stored exception array
                                                        /** @var $exceptionArray array */
                                                        $exceptionArray = @unserialize($schedulerRecord['lastexecution_failure']);
                                                        // If the exception could not be unserialized, issue a default error message