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