andrey                                   Mon, 22 Aug 2011 10:42:43 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=315270

Log:
Fix Bug #55473  mysql_pconnect leaks file descriptors on reconnect
The fix is for now in 5_4 and trunk, to be merged into 5_3 after 5.3.8
is packaged (expected today). The test case goes to all branches

Bug: https://bugs.php.net/55473 (Analyzed) mysql_pconnect leaks file 
descriptors on reconnect
      
Changed paths:
    A   php/php-src/branches/PHP_5_3/ext/mysql/tests/bug55473.phpt
    A   php/php-src/branches/PHP_5_4/ext/mysql/tests/bug55473.phpt
    U   php/php-src/branches/PHP_5_4/ext/mysqlnd/mysqlnd_net.c
    A   php/php-src/trunk/ext/mysql/tests/bug55473.phpt
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_net.c

Added: php/php-src/branches/PHP_5_3/ext/mysql/tests/bug55473.phpt
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysql/tests/bug55473.phpt                  
        (rev 0)
+++ php/php-src/branches/PHP_5_3/ext/mysql/tests/bug55473.phpt  2011-08-22 
10:42:43 UTC (rev 315270)
@@ -0,0 +1,68 @@
+--TEST--
+Bug #5547 (mysql_pconnect leaks file descriptors on reconnect)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysql.max_persistent=30
+mysql.allow_persistent=1
+--FILE--
+<?php
+       include "connect.inc";
+
+       $tmp    = NULL;
+       $link   = NULL;
+
+       function connect($host, $user, $passwd) {
+               $conn = mysql_pconnect($host, $user, $passwd);
+               if (!$conn)
+                       die(mysql_error()."\n");
+               mysql_query("set wait_timeout=1", $conn);
+               return $conn;
+       }
+
+       $conn = connect($host, $user, $passwd);
+       $opened_files = -1;
+       for($i = 0; $i < 4; $i++) {
+               /* wait while mysql closes connection */
+               sleep(3);
+
+               if (!mysql_ping($conn)) {
+                       echo "reconnect\n";
+                       $conn = connect($host, $user, $passwd);
+               }
+
+               $r = mysql_query('select 1', $conn);
+               $error = $r ? 'OK' : mysql_error();
+               if ($opened_files == -1) {
+                       $opened_files = trim(exec("lsof -np " . getmypid() . " 
| wc -l"));
+                       echo "OK\n";
+               } else if (($tmp = trim(exec("lsof -np " . getmypid() . " | wc 
-l"))) != $opened_files) {
+                       printf("[01] [%d] different number of opened_files : 
expected %d, got %d", $i, $opened_files, $tmp);
+               } else {
+                       echo "OK\n";
+               }
+       }
+
+
+       print "done!";
+?>
+--EXPECTF--
+Warning: mysql_ping(): MySQL server has gone away in %s on line %d
+reconnect
+OK
+
+Warning: mysql_ping(): MySQL server has gone away in %s on line %d
+reconnect
+OK
+
+Warning: mysql_ping(): MySQL server has gone away in %s on line %d
+reconnect
+OK
+
+Warning: mysql_ping(): MySQL server has gone away in %s on line %d
+reconnect
+OK
+done!
\ No newline at end of file

Added: php/php-src/branches/PHP_5_4/ext/mysql/tests/bug55473.phpt
===================================================================
--- php/php-src/branches/PHP_5_4/ext/mysql/tests/bug55473.phpt                  
        (rev 0)
+++ php/php-src/branches/PHP_5_4/ext/mysql/tests/bug55473.phpt  2011-08-22 
10:42:43 UTC (rev 315270)
@@ -0,0 +1,68 @@
+--TEST--
+Bug #5547 (mysql_pconnect leaks file descriptors on reconnect)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysql.max_persistent=30
+mysql.allow_persistent=1
+--FILE--
+<?php
+       include "connect.inc";
+
+       $tmp    = NULL;
+       $link   = NULL;
+
+       function connect($host, $user, $passwd) {
+               $conn = mysql_pconnect($host, $user, $passwd);
+               if (!$conn)
+                       die(mysql_error()."\n");
+               mysql_query("set wait_timeout=1", $conn);
+               return $conn;
+       }
+
+       $conn = connect($host, $user, $passwd);
+       $opened_files = -1;
+       for($i = 0; $i < 4; $i++) {
+               /* wait while mysql closes connection */
+               sleep(3);
+
+               if (!mysql_ping($conn)) {
+                       echo "reconnect\n";
+                       $conn = connect($host, $user, $passwd);
+               }
+
+               $r = mysql_query('select 1', $conn);
+               $error = $r ? 'OK' : mysql_error();
+               if ($opened_files == -1) {
+                       $opened_files = trim(exec("lsof -np " . getmypid() . " 
| wc -l"));
+                       echo "OK\n";
+               } else if (($tmp = trim(exec("lsof -np " . getmypid() . " | wc 
-l"))) != $opened_files) {
+                       printf("[01] [%d] different number of opened_files : 
expected %d, got %d", $i, $opened_files, $tmp);
+               } else {
+                       echo "OK\n";
+               }
+       }
+
+
+       print "done!";
+?>
+--EXPECTF--
+Warning: mysql_ping(): MySQL server has gone away in %s on line %d
+reconnect
+OK
+
+Warning: mysql_ping(): MySQL server has gone away in %s on line %d
+reconnect
+OK
+
+Warning: mysql_ping(): MySQL server has gone away in %s on line %d
+reconnect
+OK
+
+Warning: mysql_ping(): MySQL server has gone away in %s on line %d
+reconnect
+OK
+done!
\ No newline at end of file

Modified: php/php-src/branches/PHP_5_4/ext/mysqlnd/mysqlnd_net.c
===================================================================
--- php/php-src/branches/PHP_5_4/ext/mysqlnd/mysqlnd_net.c      2011-08-22 
09:36:26 UTC (rev 315269)
+++ php/php-src/branches/PHP_5_4/ext/mysqlnd/mysqlnd_net.c      2011-08-22 
10:42:43 UTC (rev 315270)
@@ -115,6 +115,17 @@

        net->packet_no = net->compressed_envelope_packet_no = 0;

+       if (net->stream) {
+               /* close before opening a new one */
+               DBG_INF_FMT("Freeing stream. abstract=%p", 
net->stream->abstract);
+               if (net->persistent) {
+                       php_stream_free(net->stream, 
PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
+               } else {
+                       php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);
+               }
+               net->stream = NULL;
+       }
+
        if (scheme_len > (sizeof("pipe://") - 1) && !memcmp(scheme, "pipe://", 
sizeof("pipe://") - 1)) {
                if (persistent) {
                        streams_options |= STREAM_OPEN_PERSISTENT;

Added: php/php-src/trunk/ext/mysql/tests/bug55473.phpt
===================================================================
--- php/php-src/trunk/ext/mysql/tests/bug55473.phpt                             
(rev 0)
+++ php/php-src/trunk/ext/mysql/tests/bug55473.phpt     2011-08-22 10:42:43 UTC 
(rev 315270)
@@ -0,0 +1,68 @@
+--TEST--
+Bug #5547 (mysql_pconnect leaks file descriptors on reconnect)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysql.max_persistent=30
+mysql.allow_persistent=1
+--FILE--
+<?php
+       include "connect.inc";
+
+       $tmp    = NULL;
+       $link   = NULL;
+
+       function connect($host, $user, $passwd) {
+               $conn = mysql_pconnect($host, $user, $passwd);
+               if (!$conn)
+                       die(mysql_error()."\n");
+               mysql_query("set wait_timeout=1", $conn);
+               return $conn;
+       }
+
+       $conn = connect($host, $user, $passwd);
+       $opened_files = -1;
+       for($i = 0; $i < 4; $i++) {
+               /* wait while mysql closes connection */
+               sleep(3);
+
+               if (!mysql_ping($conn)) {
+                       echo "reconnect\n";
+                       $conn = connect($host, $user, $passwd);
+               }
+
+               $r = mysql_query('select 1', $conn);
+               $error = $r ? 'OK' : mysql_error();
+               if ($opened_files == -1) {
+                       $opened_files = trim(exec("lsof -np " . getmypid() . " 
| wc -l"));
+                       echo "OK\n";
+               } else if (($tmp = trim(exec("lsof -np " . getmypid() . " | wc 
-l"))) != $opened_files) {
+                       printf("[01] [%d] different number of opened_files : 
expected %d, got %d", $i, $opened_files, $tmp);
+               } else {
+                       echo "OK\n";
+               }
+       }
+
+
+       print "done!";
+?>
+--EXPECTF--
+Warning: mysql_ping(): MySQL server has gone away in %s on line %d
+reconnect
+OK
+
+Warning: mysql_ping(): MySQL server has gone away in %s on line %d
+reconnect
+OK
+
+Warning: mysql_ping(): MySQL server has gone away in %s on line %d
+reconnect
+OK
+
+Warning: mysql_ping(): MySQL server has gone away in %s on line %d
+reconnect
+OK
+done!
\ No newline at end of file

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_net.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_net.c 2011-08-22 09:36:26 UTC (rev 
315269)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_net.c 2011-08-22 10:42:43 UTC (rev 
315270)
@@ -115,6 +115,17 @@

        net->packet_no = net->compressed_envelope_packet_no = 0;

+       if (net->stream) {
+               /* close before opening a new one */
+               DBG_INF_FMT("Freeing stream. abstract=%p", 
net->stream->abstract);
+               if (net->persistent) {
+                       php_stream_free(net->stream, 
PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
+               } else {
+                       php_stream_free(net->stream, PHP_STREAM_FREE_CLOSE);
+               }
+               net->stream = NULL;
+       }
+
        if (scheme_len > (sizeof("pipe://") - 1) && !memcmp(scheme, "pipe://", 
sizeof("pipe://") - 1)) {
                if (persistent) {
                        streams_options |= STREAM_OPEN_PERSISTENT;

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to