Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 2.5.0b5

Bug #12038 Memory Leak when an error occures on an insert
Submitted: 2007-09-12 21:16 UTC
From: henningh Assigned:
Status: Verified Package: MDB2
PHP Version: 5.2.3 OS: Linux & Windows
Roadmaps: (Not assigned)    
Subscription  


 [2007-09-12 21:16 UTC] henningh (Henning Henkel)
Description: ------------ Hi, I think there's a bug in the error handling when an error occures on an insert. The error is in my case an failure on the insert because the value I try to insert is an unique one. The error handling works fine, the problem is, that an memory leak occures. In the test script below, everything is fine, as long as there is no data in the database. The memory usage is fine. But when i try to add a duplicate, an error is raised, as well as the memory and I get fatal error after about 855 tries. I tells me that the memory is exhausted (8MB Limit). Tried the same thin with an own native implemtation of mysqli and everything was fine. A friend of mine tried the script below on his Windows machine with the same effects. The only difference between the linux and the windows test is, that the memory leek does not end in an exhausted memory error. I'm not quite sure, if this is not a generell MDB2 problem, i had no time to check this with other database types. Test script: --------------- <?php error_reporting(E_ALL); ini_set('display_errors','1'); require_once('MDB2.php'); $dsn = 'mysqli://testuser:DrPig!@127.0.0.1/testdb'; $mdb2 = MDB2::connect($dsn,array('debug' => 0,'result_buffering' =>false)); if(PEAR::isError($mdb2)){ die($mdb2->getUserInfo()); } $a=0; for($i=1;$i<=1000;$i++){ echo 'TESTINSERT - DEBUG - Insert INTO testtable(test_id) VALUES('.$a.') <br>'; echo 'TESTINSERT - DEBUG - Iteration: '. $i . ' Memory useage at start: '.memory_get_usage().'<br/>'; $result = $mdb2->query('Insert INTO testtable(test_id) VALUES('.$a.')'); if(PEAR::isError($result)){ echo $result->getUserInfo() . '<br>'; } $a = $a +1; } ?> Expected result: ---------------- In this version of the script you should see error messages and at the end on the second run of the script an "memory exhausted" error, when runnning with 8 mb. Tried to track down this bug, but could not get far with it. As far as i have seen, the memory raises only, if an error occures and is handled in the MDB2.php Actual result: -------------- Linux: TESTINSERT - DEBUG - Insert INTO testtable(test_id) VALUES(0) TESTINSERT - DEBUG - Iteration: 1 Memory useage at start: 1075564 _doQuery: [Error message: Could not execute statement] [Last executed query: Insert INTO testtable(test_id) VALUES(0)] [Native code: 1062] [Native message: Duplicate entry '0' for key 2] TESTINSERT - DEBUG - Insert INTO testtable(test_id) VALUES(1) TESTINSERT - DEBUG - Iteration: 2 Memory useage at start: 1092244 _doQuery: [Error message: Could not execute statement] [Last executed query: Insert INTO testtable(test_id) VALUES(1)] [Native code: 1062] [Native message: Duplicate entry '1' for key 2] TESTINSERT - DEBUG - Insert INTO testtable(test_id) VALUES(2) TESTINSERT - DEBUG - Iteration: 3 Memory useage at start: 1100856 _doQuery: [Error message: Could not execute statement] [Last executed query: Insert INTO testtable(test_id) VALUES(2)] [Native code: 1062] [Native message: Duplicate entry '2' for key 2] ... _doQuery: [Error message: Could not execute statement] [Last executed query: Insert INTO testtable(test_id) VALUES(852)] [Native code: 1062] [Native message: Duplicate entry '852' for key 2] TESTINSERT - DEBUG - Insert INTO testtable(test_id) VALUES(853) TESTINSERT - DEBUG - Iteration: 854 Memory useage at start: 8378792 _doQuery: [Error message: Could not execute statement] [Last executed query: Insert INTO testtable(test_id) VALUES(853)] [Native code: 1062] [Native message: Duplicate entry '853' for key 2] TESTINSERT - DEBUG - Insert INTO testtable(test_id) VALUES(854) TESTINSERT - DEBUG - Iteration: 855 Memory useage at start: 8387344 Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 207 bytes) in /opt/lampp/lib/php/MDB2.php on line 972 Windows: TESTINSERT - DEBUG - Insert INTO testtable(test_id) VALUES(0) TESTINSERT - DEBUG - Iteration: 1 Memory useage at start: 24690688 _doQuery: [Error message: Could not execute statement] [Last executed query: Insert INTO testtable(test_id) VALUES(0)] [Native code: 1062] [Native message: Duplicate entry '0' for key 1] ... TESTINSERT - DEBUG - Insert INTO testtable(test_id) VALUES(999) TESTINSERT - DEBUG - Iteration: 1000 Memory useage at start: 33779712 _doQuery: [Error message: Could not execute statement] [Last executed query: Insert INTO testtable(test_id) VALUES(999)] [Native code: 1062] [Native message: Duplicate entry '999' for key 1]

Comments

 [2007-09-19 20:48 UTC] quipo (Lorenzo Alberton)
Confirmed. It looks like a leak in MDB2_Error? Can you profile the script with Xdebug and send me the results? TIA
 [2008-03-21 11:59 UTC] henningh (Henning Henkel)
Hi, sorry it took so long, hadn't had time before. I started to trace the problem with Xdebug yesterday, but hadn't much luck to identify the problem yet. I changed the body my first test script a bit, but basically it still does the same stuff. The error on the insert is a different one, but i don't think this matters. I can send you the result per eMail if you like, cause the trace of two iterations is about 270 lines long and imho not very readable if i post it here. Cheers
 [2012-10-26 05:29 UTC] danielc (Daniel Convissor)
-Package: MDB2_Driver_mysqli +Package: MDB2
The problem still exists. I added testBug12038() in tests/Standard/BugsTest.php and here's a short reproduce script. It's an issue with the error classes, no query is necessary. require 'PEAR.php'; require 'MDB2.php'; for ($i = 0; $i < 1000; $i++) { $pear = new PEAR; // Okay. //$pear->raiseError(null, 1, 'mode', array(), 'hi'); //$pear->raiseError(null, 1, 'mode', array(), 'hi', 'StdClass', true); // Leaks $pear->raiseError(null, 1, 'mode', array(), 'hi', 'MDB2_Error', true); echo memory_get_usage() . "\n"; }