From 87b5e26063529a7a129ee6421a52d467c7896a15 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 24 May 2018 04:07:39 +0000 Subject: [PATCH 1/6] Do a hard exit when the SQL connection went down --- include/dba.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/dba.php b/include/dba.php index 1d3b43214..f3ec0507f 100644 --- a/include/dba.php +++ b/include/dba.php @@ -473,6 +473,12 @@ class dba { logger('DB Error '.self::$errorno.': '.self::$error."\n". System::callstack(8)."\n".self::replaceParameters($sql, $params)); + // It doesn't make sense to continue when the database connection was lost + if ($errorno == 2006) { + logger('Giving up because of database error '.$errorno.': '.$error); + exit(1); + } + self::$error = $error; self::$errorno = $errorno; } From 1bce39120dc0a92910375942e424fc815c21c33c Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 24 May 2018 21:19:59 +0000 Subject: [PATCH 2/6] Reconnect after the connection had been lost. --- include/dba.php | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/include/dba.php b/include/dba.php index f3ec0507f..88f298ec9 100644 --- a/include/dba.php +++ b/include/dba.php @@ -23,6 +23,7 @@ class dba { private static $errorno = 0; private static $affected_rows = 0; private static $in_transaction = false; + private static $in_retrial = false; private static $relation = []; public static function connect($serveraddr, $user, $pass, $db) { @@ -49,6 +50,7 @@ class dba { $db = trim($db); if (!(strlen($server) && strlen($user))) { +echo "1"; return false; } @@ -102,6 +104,21 @@ class dba { return self::$connected; } + public static function reconnect() { + // This variable is only defined here again to prevent warning messages + // It is a local variable and should hopefully not interfere with the global one. + $a = new App(dirname(__DIR__)); + + // We have to the the variable to "null" to force a new connection + self::$db = null; + include '.htconfig.php'; + + $ret = self::connect($db_host, $db_user, $db_pass, $db_data); + unset($db_host, $db_user, $db_pass, $db_data); + + return $ret; + } + /** * @brief Returns the MySQL server version string * @@ -473,10 +490,18 @@ class dba { logger('DB Error '.self::$errorno.': '.self::$error."\n". System::callstack(8)."\n".self::replaceParameters($sql, $params)); - // It doesn't make sense to continue when the database connection was lost + // On a lost connection we try to reconnect - but only once. if ($errorno == 2006) { - logger('Giving up because of database error '.$errorno.': '.$error); - exit(1); + if (self::$in_retrial || !self::reconnect()) { + // It doesn't make sense to continue when the database connection was lost + logger('Giving up because of database error '.$errorno.': '.$error); + exit(1); + } else { + // We try it again + logger('Reconnected after database error '.$errorno.': '.$error); + self::$in_retrial = true; + return self::p($sql, $params); + } } self::$error = $error; From f8230badba619b32de4c7ed7d07c403e6f21c16e Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 24 May 2018 21:46:57 +0000 Subject: [PATCH 3/6] Avoid problems with better variable naming --- include/dba.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/dba.php b/include/dba.php index 88f298ec9..786143783 100644 --- a/include/dba.php +++ b/include/dba.php @@ -449,23 +449,23 @@ echo "1"; break; } - $params = ''; + $param_types = ''; $values = []; foreach ($args AS $param => $value) { if (is_int($args[$param])) { - $params .= 'i'; + $param_types .= 'i'; } elseif (is_float($args[$param])) { - $params .= 'd'; + $param_types .= 'd'; } elseif (is_string($args[$param])) { - $params .= 's'; + $param_types .= 's'; } else { - $params .= 'b'; + $param_types .= 'b'; } $values[] = &$args[$param]; } if (count($values) > 0) { - array_unshift($values, $params); + array_unshift($values, $param_types); call_user_func_array([$stmt, 'bind_param'], $values); } @@ -488,7 +488,7 @@ echo "1"; $errorno = self::$errorno; logger('DB Error '.self::$errorno.': '.self::$error."\n". - System::callstack(8)."\n".self::replaceParameters($sql, $params)); + System::callstack(8)."\n".self::replaceParameters($sql, $args)); // On a lost connection we try to reconnect - but only once. if ($errorno == 2006) { @@ -500,7 +500,7 @@ echo "1"; // We try it again logger('Reconnected after database error '.$errorno.': '.$error); self::$in_retrial = true; - return self::p($sql, $params); + return self::p($sql, $args); } } From de609e49f0446bb3a000760d90c3468c54cc1497 Mon Sep 17 00:00:00 2001 From: Michael Date: Thu, 24 May 2018 22:00:54 +0000 Subject: [PATCH 4/6] Improved logging --- include/dba.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/dba.php b/include/dba.php index 786143783..f915d7837 100644 --- a/include/dba.php +++ b/include/dba.php @@ -494,7 +494,11 @@ echo "1"; if ($errorno == 2006) { if (self::$in_retrial || !self::reconnect()) { // It doesn't make sense to continue when the database connection was lost - logger('Giving up because of database error '.$errorno.': '.$error); + if (self::$in_retrial) { + logger('Giving up retrial because of database error '.$errorno.': '.$error); + } else { + logger("Couldn't reconnect after database error ".$errorno.': '.$error); + } exit(1); } else { // We try it again From 8584e09e126b8c34d16761250205b4e1534ad02b Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 11 Jun 2018 03:45:45 +0000 Subject: [PATCH 5/6] Store the database credentials for reconnect --- bin/daemon.php | 6 +++--- include/dba.php | 40 +++++++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/bin/daemon.php b/bin/daemon.php index b8c8d2e34..acb26d819 100755 --- a/bin/daemon.php +++ b/bin/daemon.php @@ -119,6 +119,7 @@ if ($pid = pcntl_fork()) { // We lose the database connection upon forking dba::connect($db_host, $db_user, $db_pass, $db_data); +unset($db_host, $db_user, $db_pass, $db_data); Config::set('system', 'worker_daemon_mode', true); @@ -143,10 +144,9 @@ while (true) { Worker::spawnWorker($do_cron); if ($do_cron) { - // We force a disconnect and reconnect of the database connection. + // We force a reconnect of the database connection. // This is done to ensure that the connection don't get lost over time. - dba::disconnect(); - dba::connect($db_host, $db_user, $db_pass, $db_data); + dba::reconnect(); $last_cron = time(); } diff --git a/include/dba.php b/include/dba.php index 550fbe255..b21b01b6d 100644 --- a/include/dba.php +++ b/include/dba.php @@ -25,6 +25,10 @@ class dba { private static $in_transaction = false; private static $in_retrial = false; private static $relation = []; + private static $db_serveraddr = ''; + private static $db_user = ''; + private static $db_pass = ''; + private static $db_name = ''; public static function connect($serveraddr, $user, $pass, $db) { if (!is_null(self::$db) && self::connected()) { @@ -35,6 +39,12 @@ class dba { $stamp1 = microtime(true); + // We are storing these values for being able to perform a reconnect + self::$db_serveraddr = $serveraddr; + self::$db_user = $user; + self::$db_pass = $pass; + self::$db_name = $db; + $serveraddr = trim($serveraddr); $serverdata = explode(':', $serveraddr); @@ -50,7 +60,6 @@ class dba { $db = trim($db); if (!(strlen($server) && strlen($user))) { -echo "1"; return false; } @@ -94,21 +103,6 @@ echo "1"; return self::$connected; } - public static function reconnect() { - // This variable is only defined here again to prevent warning messages - // It is a local variable and should hopefully not interfere with the global one. - $a = new App(dirname(__DIR__)); - - // We have to the the variable to "null" to force a new connection - self::$db = null; - include '.htconfig.php'; - - $ret = self::connect($db_host, $db_user, $db_pass, $db_data); - unset($db_host, $db_user, $db_pass, $db_data); - - return $ret; - } - /** * Disconnects the current database connection */ @@ -129,6 +123,16 @@ echo "1"; } } + /** + * Perform a reconnect of an existing database connection + */ + public static function reconnect() { + self::disconnect(); + + $ret = self::connect(self::$db_serveraddr, self::$db_user, self::$db_pass, self::$db_name); + return $ret; + } + /** * Return the database object. * @return PDO|mysqli @@ -523,7 +527,9 @@ echo "1"; // We try it again logger('Reconnected after database error '.$errorno.': '.$error); self::$in_retrial = true; - return self::p($sql, $args); + $ret = self::p($sql, $args); + self::$in_retrial = false; + return $ret; } } From 738644a0069181187dfed2fbd9ce0fb344b8ffb9 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 11 Jun 2018 03:56:19 +0000 Subject: [PATCH 6/6] Quit if database connection was lost during "e" --- include/dba.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/dba.php b/include/dba.php index b21b01b6d..c0617af8e 100644 --- a/include/dba.php +++ b/include/dba.php @@ -598,6 +598,13 @@ class dba { logger('DB Error '.self::$errorno.': '.self::$error."\n". System::callstack(8)."\n".self::replaceParameters($sql, $params)); + // On a lost connection we simply quit. + // A reconnect like in self::p could be dangerous with modifications + if ($errorno == 2006) { + logger('Giving up because of database error '.$errorno.': '.$error); + exit(1); + } + self::$error = $error; self::$errorno = $errorno; }