Bug #20298 [Fbk->NoF]: [PATCH] odbc.check_persistent not working

From: Date: Sun, 05 Nov 2017 04:22:35 +0000
Subject: Bug #20298 [Fbk->NoF]: [PATCH] odbc.check_persistent not working
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-212442@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=20298&edit=1

 ID:               20298
 Updated by:       php-bugs@lists.php.net
 Reported by:      phpbug at tab1 dot clara dot co dot uk
 Summary:          [PATCH] odbc.check_persistent not working
-Status:           Feedback
+Status:           No Feedback
 Type:             Bug
 Package:          ODBC related
 Operating System: *
 PHP Version:      5CVS-2004-04-13
 Private report:   N

 New Comment:

No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.


Previous Comments:
------------------------------------------------------------------------
[2017-10-22 23:43:39] kalle@php.net

Is this still an issue with ODBC in PHP7? 

I apologies for the long wait of a little over 8 years since the last @php.net reply, our lines have
been extremely flooded and not enough personal to handle the requests.

------------------------------------------------------------------------
[2009-05-13 13:00:34] phpbug at tab1 dot clara dot co dot uk

That doesn't seem to have fixed it, after killing the connections on the first reload of the
test page I get:

Warning: odbc_exec() [function.odbc-exec]: SQL error: [Microsoft][ODBC SQL Server
Driver][DBNETLIB]ConnectionWrite (send())., SQL state 01000 in SQLExecDirect in
C:\InetPub\wwwroot\dbtest.php on line 10

and on the second:

Warning: odbc_exec() [function.odbc-exec]: SQL error: [Microsoft][ODBC SQL Server
Driver]Communication link failure, SQL state 08S01 in SQLExecDirect in C:\InetPub\wwwroot\dbtest.php
on line 10

------------------------------------------------------------------------
[2009-05-12 02:14:42] jani@php.net

Please try using this CVS snapshot:

  http://snaps.php.net/php5.2-latest.tar.gz
 
For Windows:

  http://windows.php.net/snapshots/



------------------------------------------------------------------------
[2005-07-27 10:57:57] t-yonetani+php at ergobrains dot co dot jp

Here's a patch written according to phpbugs at kevin dot offwhite dot net's
suggestion(I hope space and tabs won't be damanged).  We're using a similar
version(just by replacing SQLGetInfo() with SQLGetConnectAttr()) on a spare
machine, and odbc_pconnect() seems to be working so far.  Uncommenting out
the code for fixing #15758 is a bit scary, but I believe it should be OK.

Index: php_odbc.c
===================================================================
RCS file: /repository/php-src/ext/odbc/php_odbc.c,v
retrieving revision 1.143.2.12
diff -u -r1.143.2.12 php_odbc.c
--- php_odbc.c	14 Jun 2003 03:37:30 -0000	1.143.2.12
+++ php_odbc.c	27 Jul 2005 08:47:05 -0000
@@ -2156,6 +2156,29 @@
 }
 /* }}} */
 
+/* {{{ is_connection_dead */
+static int is_connection_dead(odbc_connection *db_conn)
+{
+#if defined(HAVE_IBMDB2)
+#else
+	UCHAR d_name[32];
+	SWORD len;
+#endif
+	SQLINTEGER dead;
+	RETCODE ret;
+
+#if defined(HAVE_IBMDB2)
+	ret = SQLGetConnectAttr(db_conn->hdbc, SQL_ATTR_CONNECTION_DEAD, &dead,
+							0, NULL);
+#else
+	ret = SQLGetInfo(db_conn->hdbc, SQL_DATA_SOURCE_READ_ONLY, d_name,
+					 sizeof(d_name), &len);
+	dead = len == 0;
+#endif
+	return ret != SQL_SUCCESS || dead;
+}
+/* }}} */
+
 /* Persistent connections: two list-types le_pconn, le_conn and a plist
  * where hashed connection info is stored together with index pointer to
  * the actual link of type le_pconn in the list. Only persistent 
@@ -2282,23 +2305,13 @@
 			 * check to see if the connection is still in place (lurcher)
 			 */
 			if(ODBCG(check_persistent)){
-				RETCODE ret;
-				UCHAR d_name[32];
-				SWORD len;
-
-				ret = SQLGetInfo(db_conn->hdbc, 
-					SQL_DATA_SOURCE_READ_ONLY, 
-					d_name, sizeof(d_name), &len);
-
-				if(ret != SQL_SUCCESS || len == 0) {
+				if(is_connection_dead(db_conn)) {
 					zend_hash_del(&EG(persistent_list), hashed_details, hashed_len + 1);
-					/* Commented out to fix a possible double closure error 
-					 * when working with persistent connections as submitted by
-					 * bug #15758
-					 *
-					 * safe_odbc_disconnect(db_conn->hdbc);
-					 * SQLFreeConnect(db_conn->hdbc);
+					/*
+					 * now that we know the connection is dead, just free
+					 * the DBC handle without issuing SQLDisconnect().
 					 */
+					SQLFreeConnect(db_conn->hdbc);
 					goto try_and_get_another_connection;
 				}
 			}

------------------------------------------------------------------------
[2004-06-04 22:06:49] phpbugs at kevin dot offwhite dot net

Well, after some additional research I have turned up what I think is the exact cause of the bug,
but I don't feel qualified to implement the solution.

In the php code, at line 2271 in php_odbc.c ( http://lxr.php.net/source/php-src/ext/odbc/php_odbc.c#2271
), php calls SQLGetInfo() passing a parameter of SQL_DATA_SOURCE_READ_ONLY to try and determine if
the connection is alive or not.  While this may work in some odbc drivers, it is not the
"official" way of asking if the connection is dead.  According to my driver supplier ( http://www-912.ibm.com/o_dir/odbcforum.nsf/8178b1c14b1e9b6b8525624f0062fe9f/B0CFDBA3D8DBAC0F86256EA80077D2B9?OpenDocument
) and the Microsoft's ODBC Programmer's reference ( http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcodbc_connection_pooling.asp
), the correct method is to use SQLGetConnectAttr() to check the Attribute SQL_ATTR_CONNECTION_DEAD.


Steps to reproduce:
  1) Use PHP's odbc_pconnect() function with the iSeries ODBC Driver for Linux.
  2) Allow the connection to idle long enough for the Server to disconnect.
  3) Try and use the connection which was disconnected by the server.

Expected result:
1)  PHP calls SQLGetConnectAttr() to check SQL_ATTR_CONNECTION_DEAD, which returns SQL_ERROR.  
2) PHP removes the connection from its internal list, creates a new persistent connection, and
returns that new connection to the php script
3) call to odbc_exec() succeeds.

Actual result:
1) PHP calls SQLGetInfo() to check SQL_DATA_SOURCE_READ_ONLY, which returns SQL_SUCCESS
2) PHP believes this to be a valid connection, and returns this connection to the php script
3) call to odbc_exec() fails.

------------------------------------------------------------------------


The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at

    https://bugs.php.net/bug.php?id=20298


--
Edit this bug report at https://bugs.php.net/bug.php?id=20298&edit=1


Thread (25 messages)

« previous php.bugs (#212442) next »