]> granicus.if.org Git - php/commitdiff
Fix Bug #55473 mysql_pconnect leaks file descriptors on reconnect
authorAndrey Hristov <andrey@php.net>
Mon, 22 Aug 2011 10:42:43 +0000 (10:42 +0000)
committerAndrey Hristov <andrey@php.net>
Mon, 22 Aug 2011 10:42:43 +0000 (10:42 +0000)
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

ext/mysql/tests/bug55473.phpt [new file with mode: 0644]
ext/mysqlnd/mysqlnd_net.c

diff --git a/ext/mysql/tests/bug55473.phpt b/ext/mysql/tests/bug55473.phpt
new file mode 100644 (file)
index 0000000..8d42744
--- /dev/null
@@ -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
index 6821c5f2056328cf99756ce1a2c1458a7c5649e2..606d919e3bd1cc02c4648c938061c759e94f4c0d 100644 (file)
@@ -115,6 +115,17 @@ MYSQLND_METHOD(mysqlnd_net, connect)(MYSQLND_NET * net, const char * const schem
 
        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;