php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #35205 oci_connect is not closing opened connections after script execution
Submitted: 2005-11-13 01:56 UTC Modified: 2005-11-25 11:19 UTC
From: robertg2 at hope dot ac dot uk Assigned: tony2001 (profile)
Status: Closed Package: OCI8 related
PHP Version: 5.0.5 OS: Solaris 8
Private report: No CVE-ID: None
 [2005-11-13 01:56 UTC] robertg2 at hope dot ac dot uk
Description:
------------
Today I've been developing on a web server connecting to a remote Oracle 9i database using the latest 1.1.1 oci8 extension from PECL.

Unfortunately, towards the end of the day I started receiving the Oracle error ORA-00020, indicating that the connections from the web server to the database server were not closing automatically at script execution end as I expected.

'netstat -an | grep 1521 | wc -l' on the web server reports 436 which is waaaaaay too high for a Saturday and is not representative of the load we are receiving.

I understand that I am able to close the connections explicitly, but I assumed that the connections would themselves be closed automatically at end of script execution?

I just installed oci8 1.1.1 yesterday and started developing on it today.

Thanks,
Gareth

Reproduce code:
---------------
In theory:

<?php

oci_connect($user, $password, $db);

?>

and refresh a couple of hundred times.

Expected result:
----------------
oci_connect($user, $password, $db) to return false with the error reported by oci_error to be ORA-00020

Actual result:
--------------
not available

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-11-13 13:43 UTC] robertg2 at hope dot ac dot uk
Hi there,

It's now the morning, and I've verified this behaviour.

<?php
$conn = oci_connect("user", "pw", "db");
?>

'netstat -an | grep 1521.*ESTABLISHED | wc -l' reports an incremented number of connections after script execution ends.
 [2005-11-13 13:55 UTC] wez@php.net
That doesn't sound right (hence your bug report); can you verify that you really are using the latest PECL OCI8 extension?  Check your phpinfo() output.
 [2005-11-13 14:52 UTC] robertg2 at hope dot ac dot uk
Hi Wez,

It's definitely 1.1.1 - unless I've gone totally delirious.  phpinfo() reports oci8 '$Revision: 1.274 $' (??), and lists the new oci8 directives and default values.

If you'd like the URL to the phpinfo() page, give me a shout.

Thanks,
Gareth
 [2005-11-13 17:25 UTC] robertg2 at hope dot ac dot uk
Would the fact that it's being run with Apache2 using a threaded MPM have anything to do with it?
 [2005-11-13 20:23 UTC] tony2001@php.net
Just to be sure:
Do you have a debugger there?
If yes, please check that functions "php_oci_connection_close" and "OCIServerDetach" are being called (just set a breakpoint there), 'cause I'm absolutely sure I can't reproduce it on Linux.
Thanks.
 [2005-11-13 21:32 UTC] robertg2 at hope dot ac dot uk
Ahh Tony.  Last time I touched C was in 1997... there's no debugger installed... space on /usr/local is severely limited... this PHP project has got to be finished by Wednesday... and if anything breaks again tonight it'll be my head on a stick on Monday morning.

That is, I'd love to help right now but am not able to.  

Have reconfirmed the behaviour again.  Also, thought this snippet might be of some use:

<?php
$conn = oci_connect("user", "pw", "db");
echo oci_close($conn);
?>

oci_close($conn) returns 1 and 'netstat -an | grep 1521.*ESTABLISHED | wc -l' does NOT increment.  That is, if oci_close is called the connection closes, but if it doesn't it stays open forever.
 [2005-11-14 00:34 UTC] tony2001@php.net
It'll take some time for me to install OCI client at Solaris and build PHP --with-oci8, so I doubt I'll be able to do it in the nearest days. 
Though, that doesn't mean that I won't do it at all.
I believe it'd be easier to install debugger and to see if this is a problem of PHP or a problem of Oracle Client on Solaris (and to help *yourself* this way).
Reconfirming and re-re-confirming doesn't add any value, believe me.
 [2005-11-14 01:39 UTC] robertg2 at hope dot ac dot uk
I believe you.  We both want the same thing right?

In this role, I answer to my boss first.  To the University's students second.  And to the PHP community a far third.

I'm well aware that to fix this bug I should to help you, and that's why I shall schedule maintenance and take one of the web servers out of the load balancing circuit when is convenient for me and the organisation and the students it serves.

A traveller from Bug #29779, there's nothing more in PHP - and I'm a PHP fanatic - to see a reliable oci8 library.

I'm lurking on Undernet about to ambush you when you get on :p.
 [2005-11-15 14:47 UTC] tony2001@php.net
Just for the record: I can't reproduce on Linux and on Solaris with Apache2/prefork.

 [2005-11-15 19:09 UTC] tony2001@php.net
... and it works fine even if the MPM if "worker", so this is not a multithreading related issue.
Please try to build PHP with Oracle Instant Client and see if it helps.

 [2005-11-20 01:55 UTC] robertg2 at hope dot ac dot uk
Sorry for the delay in testing.

The connection is closed off correctly when compiled against InstantClient 10.
 [2005-11-20 13:15 UTC] robertg2 at hope dot ac dot uk
Tony,

Unfortunately it doesn't look like it picked up the instant client in compilation as the new style \\HOSTNAME\DBNAME referencing feature doesn't work.  So still it's unclear whether compiling with the instant client would reproduce the problem.

Will try again tonight.
 [2005-11-20 13:18 UTC] robertg2 at hope dot ac dot uk
oh and... as for the comment I made at 1:55am... that was a mistake.  I hadn't taken the oci_close statement out of the code.

Sorry :(
 [2005-11-21 02:39 UTC] robertg2 at hope dot ac dot uk
Okay, for real this time:

Using the 32-bit instantclient 10 doesn't seem to have an effect on the behaviour in question.

<?
oci_connect('user', 'pw', '//HOST/DBNAME');
?>

After browsing to a script such as this via the web, the connection to the database remains.
 [2005-11-22 11:48 UTC] tony2001@php.net
Works fine here, both on Linux and Solaris.
Please provide an account on this server or try on a different server yourself.
 [2005-11-22 12:00 UTC] robertg2 at hope dot ac dot uk
We've tried it on Linux with Instant Client 10 - it works fine.

I shall speak with my superiors about providing an account but it seems unlikely we will be able to do so.  Is there no other way to progress this bug report further?
 [2005-11-22 12:10 UTC] tony2001@php.net
Since I can't reproduce it even on Solaris, you have to make a research on your own:
Enable oci_internal_debug(true); and check its output.
Make sure php_oci_connection_close() function is called on every connection resource.
 [2005-11-25 07:50 UTC] cjbj at hotmail dot com
Antony, I've looked at session cleanup.

Problem 1:

    Incorrect order of OCISessionEnd and OCIServerDetach calls in
    php_oci_connection_close()

    The "Terminating the Application" section in chapter 2 of the OCI
    manual: http://download-west.oracle.com/docs/cd/B19306_01/
    appdev.102/b14250/oci02bas.htm#sthref217 says to call
    OCISessionEnd before calling OCIServerDetach.

Problem 2:

    In php_oci_connection_close(), connection->session is used after
    it has been freed.

Problem 3:

    In php_oci_connection_close() why are there some "free" and some
    "efree" calls?

Problem 4:

    In php_oci_cleanup_global_handles() the error handle should be of
    type OCI_HTYPE_ERROR, not OCI_HTYPE_ENV

Problem 5 (minor suggestion):

    Calls to OCIEnvInit, OCIHandleAlloc, OCIErrorGet & OCIHandleFree in
    php_oci_init_global_handles() could use PHP_OCI_CALL() so debug trace
    is generated.

    Call to OCIInitialize in PHP_MINIT_FUNCTION() could use
    PHP_OCI_CALL().

    Call to OCITerminate in PHP_MSHUTDOWN_FUNCTION() could use
    PHP_OCI_CALL().

A suggested patch is below.  Please review and test as I may have
misunderstood the solutions for problems 3 and 5, or not have taken
care of some special cases.

I have been unable to verify the patch solves the problem because I
only see the problem on Windows, but can only build on Linux.


--- oci8.c.1.283	2005-11-25 15:52:57.000000000 +1100
+++ oci8.c	2005-11-25 17:18:41.006806296 +1100
@@ -396,13 +396,13 @@
   sb4 error_code = 0;
   text tmp_buf[PHP_OCI_ERRBUF_LEN];

-  errcode = OCIEnvInit (&OCI_G(env), OCI_DEFAULT, 0, NULL);
+  errcode = PHP_OCI_CALL(OCIEnvInit, (&OCI_G(env), OCI_DEFAULT, 0, NULL));

   if (errcode == OCI_ERROR) {
     goto oci_error;
   }

-  errcode = OCIHandleAlloc (OCI_G(env), (dvoid **)&OCI_G(err), OCI_HTYPE_ERROR, 0, NULL);
+  errcode = PHP_OCI_CALL(OCIHandleAlloc, (OCI_G(env), (dvoid **)&OCI_G(err), OCI_HTYPE_ERROR, 0, NULL));

   if (errcode == OCI_ERROR || errcode == OCI_SUCCESS_WITH_INFO) {
     goto oci_error;
@@ -412,7 +412,7 @@

 oci_error:

-  OCIErrorGet(OCI_G(env), (ub4)1, NULL, &error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR);
+  PHP_OCI_CALL(OCIErrorGet, (OCI_G(env), (ub4)1, NULL, &error_code, tmp_buf, (ub4)PHP_OCI_ERRBUF_LEN, (ub4)OCI_HTYPE_ERROR));

   if (error_code) {
     int tmp_buf_len = strlen(tmp_buf);
@@ -424,7 +424,7 @@
     if (errcode != OCI_SUCCESS_WITH_INFO) {
       php_error_docref(NULL TSRMLS_CC, E_WARNING, "OCI_ERROR: %s", tmp_buf);

-      OCIHandleFree((dvoid *) OCI_G(env), OCI_HTYPE_ENV);
+      PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(env), OCI_HTYPE_ENV));

       OCI_G(env) = NULL;
       OCI_G(err) = NULL;
@@ -441,7 +441,7 @@
 static void php_oci_cleanup_global_handles(TSRMLS_D)
 {
   if (OCI_G(err)) {
-    PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(err), OCI_HTYPE_ENV));
+    PHP_OCI_CALL(OCIHandleFree, ((dvoid *) OCI_G(err), OCI_HTYPE_ERROR));
     OCI_G(err) = NULL;
   }

@@ -480,7 +480,7 @@
 #endif

 #if !HAVE_OCI_ENV_CREATE
-  OCIInitialize(PHP_OCI_INIT_MODE, NULL, NULL, NULL, NULL);
+  PHP_OCI_CALL(OCIInitialize, (PHP_OCI_INIT_MODE, NULL, NULL, NULL, NULL));
 #endif

   ZEND_INIT_MODULE_GLOBALS(oci, php_oci_init_globals, NULL);
@@ -609,7 +609,7 @@
 #endif

 #if !HAVE_OCI_ENV_CREATE
-  OCITerminate(OCI_DEFAULT);
+  PHP_OCI_CALL(OCITerminate, (OCI_DEFAULT));
 #endif

   return SUCCESS;
@@ -1408,10 +1408,18 @@
     }
   }

+  if (connection->svc && connection->session && connection->is_open) {
+    PHP_OCI_CALL(OCISessionEnd, (connection->svc, OCI_G(err), connection->session, (ub4) 0));
+  }
+
   if (connection->is_attached) {
     PHP_OCI_CALL(OCIServerDetach, (connection->server, OCI_G(err), OCI_DEFAULT));
   }

+  if (connection->svc) {
+    PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX));
+  }
+
   if (connection->err) {
     PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->err, (ub4) OCI_HTYPE_ERROR));
   }
@@ -1424,23 +1432,15 @@
     PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->server, (ub4) OCI_HTYPE_SERVER));
   }

-  if (connection->svc) {
-    if (connection->session && connection->is_open) {
-      PHP_OCI_CALL(OCISessionEnd, (connection->svc, OCI_G(err), connection->session, (ub4) 0));
-    }
-
-    PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->svc, (ub4) OCI_HTYPE_SVCCTX));
-  }
-
   if (connection->env) {
     PHP_OCI_CALL(OCIHandleFree, ((dvoid *) connection->env, OCI_HTYPE_ENV));
   }

   if (connection->is_persistent) {
     if (connection->hash_key) {
-      free(connection->hash_key);
+      efree(connection->hash_key);
     }
-    free(connection);
+    efree(connection);
   }
   else {
     if (connection->hash_key) {
 [2005-11-25 11:19 UTC] tony2001@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

Thanks, Chris.
Patch applied (well, partly).

>In php_oci_connection_close() why are there some "free" 
>and some "efree" calls?
free() for persistent handles and efree() for usual ones.
memory allocated by efree() is freed at the end of request by Zend memory manager.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 26 14:01:29 2024 UTC