Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reusing PDO statement var crashes the process

Tags:

php

mysql

pdo

I'm reusing a variable to store two different PDO mysql statements:

$stmt=$dbh->prepare("SELECT ....");   
$stmt->execute();

$stmt=$dbh->prepare("UPDATE ....");
//crash here: 
//*** Error in `/opt/lampp/bin/httpd': free(): invalid pointer: 0xf4a028dc ***
//*** Error in `/opt/lampp/bin/httpd': free(): invalid pointer: 0xf4a028dc ***
//[Mon Jun 03 19:53:48.691674 2013] [core:notice] [pid 20249] AH00052: child pid 25933 exit //signal Aborted (6)
//[Mon Jun 03 19:53:48.691727 2013] [core:notice] [pid 20249] AH00052: child pid 25952 exit //signal Aborted (6)

but if instead I use $stmt2=$dbh->prepare("UPDATE ...."); nothing weird happens and the statment executes alright. It also goes without trouble if I enable prepare emulation:

$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,true);

I tried $stmt->closeCursor() after executing the first statement and also unset($stmt) (and also both of them), producing the same crash. I'm using PHP 5.4.7. Why does this happen? Is it a bug or a really weird feature?

[UPDATE] I switched from xampp to OpenSUSE 12.3 default Apache (2.2.22) and PHP (5.3.17) and still get the same error, but a more detailed dump log: http://paste2.org/d0BtdOHI

[UPDATE 2] I've also confirmed it happens when using MySQL 5.5.27 instead of MariaDB 5.5.29 as a server, so it's definetly comming from my script and pretty much universal (going to try also a centos virtual machine just in case it's some glibc related issue from my distro...), happening with different versions of apache, mysql and php, but still don't have a clue of what can be the cause...

[UPDATE 3] Well it seems CentOS 6.4 is much nicer about it and lets me run my script without any troubles at all, and since it's what I'm using on production I guess there's nothing to worry about. Anyway I would really like to know what's happening here...

like image 796
NotGaeL Avatar asked Oct 21 '22 08:10

NotGaeL


1 Answers

I apologize for this late update, but I had a similar problem with PDO (Sybase), and I can confirm that re-using statement variables without unsetting or setting to null should definitely be avoided.

In PHP, whenever we overwrite a variable value, it first creates the new variable, and only after that it replaces and destroys the old value. In most cases that's not a problem (other than spending double the memory for allocating a single variable), but with statements it's completely different, because it wouldn't close the first statement or the cursor when it creates the second one, and some database drivers don't handle well multiple statements within the same PDO connection.

Depending on the driver you use, the PDOStatement::closeCursor() might not close the statement, so the problem persists (at http://www.php.net/manual/en/pdostatement.closecursor.php we can see that it depends on the driver, otherwise it will use PDO default that does not closes statements).

So in this case, an unset() between the PDO::prepare() makes all the difference:

$stmt=$dbh->prepare("SELECT ....");   
$stmt->execute();
unset($stmt); // or $stmt = null; --> statement is destroyed at PDO
$stmt=$dbh->prepare("UPDATE ....");
like image 176
Capilé Avatar answered Oct 27 '22 22:10

Capilé