Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:30124 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 75075 invoked by uid 1010); 7 Jun 2007 12:09:10 -0000 Delivered-To: ezmlm-scan-internals@lists.php.net Delivered-To: ezmlm-internals@lists.php.net Received: (qmail 75060 invoked from network); 7 Jun 2007 12:09:10 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 7 Jun 2007 12:09:10 -0000 Authentication-Results: pb1.pair.com header.from=php@hristov.com; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=php@hristov.com; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain hristov.com from 85.92.73.163 cause and error) X-PHP-List-Original-Sender: php@hristov.com X-Host-Fingerprint: 85.92.73.163 iko.gotobg.net Linux 2.6 Received: from [85.92.73.163] ([85.92.73.163:38525] helo=iko.gotobg.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 31/30-07620-365F7664 for ; Thu, 07 Jun 2007 08:09:08 -0400 Received: from androto.ddns.playtime.bg ([87.120.219.87] helo=[192.168.1.112]) by iko.gotobg.net with esmtpa (Exim 4.66) (envelope-from ) id 1HwGlo-00069S-Jv; Thu, 07 Jun 2007 15:07:16 +0300 Message-ID: <4667F4AE.7000204@hristov.com> Date: Thu, 07 Jun 2007 15:06:06 +0300 User-Agent: Thunderbird 1.5.0.7 (X11/20060911) MIME-Version: 1.0 To: Antony Dovgal CC: Peter Christensen , internals@lists.php.net, Georg Richter References: <4667EEEB.8040209@ordbogen.com> <4667F2B3.9030308@zend.com> In-Reply-To: <4667F2B3.9030308@zend.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - iko.gotobg.net X-AntiAbuse: Original Domain - lists.php.net X-AntiAbuse: Originator/Caller UID/GID - [0 0] / [47 12] X-AntiAbuse: Sender Address Domain - hristov.com X-Source: X-Source-Args: X-Source-Dir: Subject: Re: [PHP-DEV] Bug regarding unbuffered MySQL queries and persistent connections From: php@hristov.com (Andrey Hristov) Hi, Antony Dovgal wrote: > Hello Peter. > > The analysis looks correct. > > I'm going to apply the patch soon. > Georg, Andrey, any objections? no > On 07.06.2007 15:41, Peter Christensen wrote: >> Hi, >> >> I'm new to the list, so I apologize if this is the wrong place to post! >> >> Anyway, several years now, I've been struggling with errors such as: >> >> PHP Warning: : is not a valid MySQL result resource in >> >> >> at various places on the sites I work on. But the warnings only >> happens a few times a day, despite the thousands of visitors we have >> daily. Besides, I've carefully verified that the PHP code is in fact >> not wrong (like duplicate mysql_free_result and the likes). Eventually >> we ignored the problem due to its rarity. >> >> Lately however, the likelihood of errors at certain places in our >> system increased, which made my boss grant me indefinitely time to >> solve the problem. >> >> After some three to four days of analysis of live memory dumps, I >> traced the problem to be the active_result_id field within the >> php_mysql_conn structure. Apparently this field is not cleared when a >> persistent MySQL connection is pulled from the list, so should you >> accidentally hit that same resource id and then perform another query, >> your previous query was freed. >> >> An example: >> >> bug.php: >> >> > >> header("Content-Type: text/plain"); >> >> mysql_pconnect("hostname", "username", "password"); >> >> if ($_GET["step"] == 1) >> { >> $res = mysql_unbuffered_query("SELECT * FROM db.table"); >> echo("Created resource ".(int)$res."\n"); >> mysql_free_result($res); >> } >> else if ($_GET["step"] == 2) >> { >> $res1 = mysql_query("SELECT * FROM db.table"); >> echo("Created resource ".(int)$res1."\n"); >> $res2 = mysql_query("SELECT * FROM db.table"); >> echo("Created resource ".(int)$res2."\n"); >> mysql_free_result($res2); >> if (!is_resource($res1)) >> echo("Resource ".(int)$res1." was destroyed\n"); >> else >> mysql_free_result($res1); >> } >> ?> >> >> >> Now, if I open bug.php?step=1 and then bug.php?step=2 within the same >> HTTP connection, I get: >> >> >> bug.php?step=1: >> Created resource 4 >> >> >> bug.php?step=2: >> Created resource 4 >> Created resource 5 >> Resource 4 was destroyed >> >> >> The thing is, when bug.php?step=1 is called, a MySQL connection is >> established and resource 3 contains a MySQL structure and >> active_result_id is set to 0. Then we perform an unbuffered query >> which get resource id 4. This id is stored in active_result_id. >> >> When we call bug.php?step=2 immediately after, we get the very same >> MySQL connection as well as the active_result_id set to 4. Then we >> perform the first query, and while mysql_query actually looks for >> resource #4, it doesn't find it and so does nothing. But then it >> performs the query and creates resource #4. Finally we perform the 2nd >> query, but only this time resource #4 actually exist, so the resource >> is freed before the query is performed, thus resulting in subsequent >> errors. >> >> >> So, to summarise the problem is really quite simple. active_result_id >> is only cleared within php_mysql_do_connect if the connection is not >> persistent, or if a persistent connection was not found. So the >> natural solution is simply to clear it as it should (patch attached) >> >> >> I'm sorry if my mail is too large, but my experience with other open >> source projects, is that a full description of the cause and reason of >> a patch increase the chance of the patch getting accepted (and >> understood). >> >> >> For the record, the problem apparently affects all versions of PHP. >> (tested on various home-built versions up to and including 4.4.7, as >> well as Debian built PHP 5.2.0-8). >> I might also contact the Debian PHP maintainers regarding the bug, so >> that I won't have to use home-built packages on all our servers (or >> turn off persistent connections). >> >> >> Best regards, >> Peter Christensen >> > > Andrey