From 0d40235791886894eaf6aaf8b3c191ec28e55286 Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 21 Jun 2021 12:33:15 +0200 Subject: [PATCH] =?UTF-8?q?:card=5Ffile=5Fbox:=20N=C2=B03968=20Fix=20mutex?= =?UTF-8?q?=20being=20silently=20released=20after=20connection=20timeout?= =?UTF-8?q?=20(#209)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mutex are using their own DB connection Because the `wait_timeout` isn't specified when opening the connection, it could be closed before we released the lock : if so the lock is silently released ! We are now setting this variable directly when opening the connection to avoid such case (setting 86400s, so 1 day : this should be enough !) --- core/mutex.class.inc.php | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/core/mutex.class.inc.php b/core/mutex.class.inc.php index b743dcaf9..f9580a963 100644 --- a/core/mutex.class.inc.php +++ b/core/mutex.class.inc.php @@ -242,6 +242,8 @@ class iTopMutex * * @throws \Exception * @throws \MySQLException + * + * @since 2.7.5 3.0.0 N°3968 specify `wait_timeout` for the mutex dedicated connection */ public function InitMySQLSession() { @@ -254,10 +256,36 @@ class iTopMutex $this->hDBLink = CMDBSource::GetMysqliInstance($sServer, $sUser, $sPwd, $sSource, $bTlsEnabled, $sTlsCA, false); - if (!$this->hDBLink) - { + if (!$this->hDBLink) { throw new Exception("Could not connect to the DB server (host=$sServer, user=$sUser): ".mysqli_connect_error().' (mysql errno: '.mysqli_connect_errno().')'); } + + // Make sure that the server variable `wait_timeout` is at least 86400 seconds for this connection, + // since the lock will be released if/when the connection times out. + // Source https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html : + // > A lock obtained with GET_LOCK() is released explicitly by executing RELEASE_LOCK() or implicitly when your session terminates + // + // BEWARE: If you want to check the value of this variable, when run from an interactive console `SHOW VARIABLES LIKE 'wait_timeout'` + // will actually returns the value of the variable `interactive_timeout` which may be quite different. + $sSql = "SHOW VARIABLES LIKE 'wait_timeout'"; + $result = mysqli_query($this->hDBLink, $sSql); + if (!$result) { + throw new Exception("Failed to issue MySQL query '".$sSql."': ".mysqli_error($this->hDBLink).' (mysql errno: '.mysqli_errno($this->hDBLink).')'); + } + if ($aRow = mysqli_fetch_array($result, MYSQLI_BOTH)) { + $iTimeout = (int)$aRow[1]; + } else { + mysqli_free_result($result); + throw new Exception("No result for query '".$sSql."'"); + } + mysqli_free_result($result); + + if ($iTimeout < 86400) { + $result = mysqli_query($this->hDBLink, 'SET SESSION wait_timeout=86400'); + if ($result === false) { + throw new Exception("Failed to issue MySQL query '".$sSql."': ".mysqli_error($this->hDBLink).' (mysql errno: '.mysqli_errno($this->hDBLink).')'); + } + } }