php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login

Patch mysql_pconnect-should-reconnect-in-all-error-cases.patch for MySQL related Bug #71699

Patch version 2016-03-02 08:30 UTC

Return to Bug #71699 | Download this patch
Patch Revisions:

Developer: pch@ordbogen.com

From bd2b4007ecb231a458720c0274430cf22c415ed9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Peter=20N=C3=B8rlund?= <pch@ordbogen.com>
Date: Wed, 2 Mar 2016 09:11:51 +0100
Subject: [PATCH] mysql_pconnect should reconnect in all error cases

If mysql_ping fails, and the error code was not 2006 (CR_SERVER_GONE_ERROR),
mysql_pconnect would still reuse the connecting, causing subsequent queries to
fail.

If for instance, a PHP script ran out of memory while fetching from a MySQL
result, the reused MySQL connecting would be in an invalid state, causing
queries (and ping) to fail with 2014 (CR_COMMANDS_OUT_OF_SYNC).

Just bypassing the check for error code 2006 would cause a crash, since PHP
would attempt to use the mysql handle directly, so we close the handle and
create a new one.
---
 ext/mysql/php_mysql.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/ext/mysql/php_mysql.c b/ext/mysql/php_mysql.c
index 2d3ba60..c168a5a 100644
--- a/ext/mysql/php_mysql.c
+++ b/ext/mysql/php_mysql.c
@@ -932,20 +932,21 @@ static void php_mysql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
 			mysqlnd_end_psession(mysql->conn);
 #endif
 			if (mysql_ping(mysql->conn)) {
-				if (mysql_errno(mysql->conn) == 2006) {
+				mysql_close(mysql->conn);
 #ifndef MYSQL_USE_MYSQLND
-					if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
+				mysql->conn = mysql_init(NULL);
+				if (mysql_real_connect(mysql->conn, host, user, passwd, NULL, port, socket, client_flags)==NULL)
 #else
-					if (mysqlnd_connect(mysql->conn, host, user, passwd, passwd_len, NULL, 0, port, socket, client_flags, MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA TSRMLS_CC) == NULL)
-#endif
-					{
-						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect");
-						zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length+1);
-						efree(hashed_details);
-						MYSQL_DO_CONNECT_RETURN_FALSE();
-					}
-					mysql_options(mysql->conn, MYSQL_OPT_LOCAL_INFILE, (char *)&MySG(allow_local_infile));
+				mysql->conn = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, persistent);
+				if (mysqlnd_connect(mysql->conn, host, user, passwd, passwd_len, NULL, 0, port, socket, client_flags, MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA TSRMLS_CC) == NULL)
+#endif
+				{
+					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link to server lost, unable to reconnect");
+					zend_hash_del(&EG(persistent_list), hashed_details, hashed_details_length+1);
+					efree(hashed_details);
+					MYSQL_DO_CONNECT_RETURN_FALSE();
 				}
+				mysql_options(mysql->conn, MYSQL_OPT_LOCAL_INFILE, (char *)&MySG(allow_local_infile));
 			} else {
 #ifdef MYSQL_USE_MYSQLND
 				mysqlnd_restart_psession(mysql->conn);
-- 
1.9.1

 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Fri Dec 06 05:01:23 2019 UTC