ID: 21306 Comment by: eric dot ritchie at dorten dot com Reported By: Xuefer at 21cn dot com Status: No Feedback Bug Type: Session related Operating System: linux PHP Version: 4.3.0 New Comment:
I think I may be able to cast some light on this particular problem. First the important info: OS: Suse Linux 8.1 / Suse Linux 7.0 / Windows 2000 PHP: 4.3.1 / 4.3.0 / 4.3.1 & 4.3.2PL4 Apache: 1.3.27+ssl1.48 / same / 1.3.26 PHP is compiled into Apache on the Linux machines and inserted as a module under Windows. The application, that am developing for my company, is a large project with user management, sessions, SSL admin and non SSL user sections etc. I first started to get this problem frequently after making one particular change to the application. Since one user should only have one connection to the application, I checked the session table (in a MySQL database) and deleted all previous sessions that contained the same user ID. The problem came when someone was still using the session that was deleted. Depending apon what that user was doing at the time of the deletion, the application would either take them back to the login screen and report the session had expired (what I intended) or crash within the PEAR:throwError() method in the PEAR.php library. Checking with debug_backtrace() I could see that a constant (DB_FETCHMODE_ASSOC), passed to one of the preceeding function calls, was being corrupted during the call. I thought that there was something screwed up with the MySQL session handling code (in our application), so I switched back to using file based sessions and found the same problem to exist. After some time I found the following solution (see the comment for details): function read($id) { $hackStr = "selectedParts|a:0:{}selectedCars|a:0:{}selectedCountries|a:0:{}cartHead|a:0:{}sessionUser|a:0:{}sessionCustomer|a:0:{}"; $db = &$GLOBALS['db']; $db->setFetchMode(DB_FETCHMODE_ASSOC); $q = "SELECT * FROM ourSession WHERE id = '".$id."'"; $res = $db->query($q); if (PEAR::isError($res) || !($row = $res->fetchRow())) { // WARNING returning '' seems to crash PHP. Therefore, // I return a empty session instead. return $hackStr; } return base64_decode($row['data']); } // read() Which is of course called via session_set_save_handler(). I noted the same problem with file session handling. If the contents of the file are emptied (or the file is deleted) then the application crashed. However, if I overwrote the file with a dummy session string, then all worked well. I am guessing that the version 4.3.x of PHP have a problem initialising sessions and can cause buffer overflows under certain conditions. I hope you all find this useful! Eric Ritchie Dorten GmbH. Previous Comments: ------------------------------------------------------------------------ [2003-05-25 21:53:44] [EMAIL PROTECTED] No feedback was provided. The bug is being suspended because we assume that you are no longer experiencing the problem. If this is not the case and you are able to provide the information that was requested earlier, please do so and change the status of the bug back to "Open". Thank you. ..and this is not likely anything wrong in PHP, some broken HTML can make your script getting run twice too. ------------------------------------------------------------------------ [2003-05-20 13:13:43] xuefer at 21cn dot com sorry, i meant chance, not change ------------------------------------------------------------------------ [2003-05-20 13:11:56] xuefer at 21cn dot com sorry, i don't have change to test it yet so will soletan confirm the snapshot thx ------------------------------------------------------------------------ [2003-05-20 10:03:32] [EMAIL PROTECTED] Code being executed twice really sounds like a problem in the scripting engine to me. It could be caused or triggered by defects in the tool chain (buggy compiler optimizer, broken bison/flex). Please retest with current Stable snapshot from snaps.php.net. ------------------------------------------------------------------------ [2003-03-14 13:00:31] soletan at toxa dot de I tried to compile some information on that bug, that probably helps to understand my problems. Because this report system lacks of a support for attachments (which is quite reasonable to me, of course). But I guess you won't read >3MB text files unzipped or 86 KB archived, but binary here ... I send the compilation to anyone who likes to get. Several php-scripts, some modifications to php-source I made, two quite large but still „simple“ syslog-excerpts, a copy of output are included with that compilation. The scripts are excerpts only, because a full backup of my scripts’ source tree would take 190 KB gzipped. If you need more information (sources) to reproduce the malfunction, send me a mail, but I hope this is enough and maybe you don’t need that much additional information. Some first idea of what’s wrong: In my case this bug doesn’t immediately belong to sessions. It’s probably some scripting failure or a malfunction of how several parts of PHP-core and ext’s – zend scripting engine and altered session handler – work together. It looks like some overflow, like something’s trashing PHP’s heap. As a consequence, or in conjunction with that, PHP doesn’t end and gets dropped by maximum-execution-time observer, which then ignores any session save procedures and cleans up everything. During this the session still gets informed about restoring the ini-environment and produces the posted error message. Here is what I did: The bug appeared again and I couldn't find any place in my scripts missed to include some session_write_close() + exit() – this in consequence to my last comment! One of my scripts is a layouter (lib/layout.php), implemented as a class. I feed it with information about the body content, menu structure and else. It stores all these in a structured array. Finally I call a method named "draw()", that searches for available plugins depending on the client's browser-caps and uses one of these to produce a string, which draw() returns itself to its caller afterwards. That caller finally echo's the string right before the closing tag and the end of major script file – I used src/start.php for testing. Each trial to break the execution before calling that draw method was successful, tested with included snippet "echo 'test'; exit( 0 );" ... Now comes some interesting point: Placing the same at the first line inside the draw-method, I get "test" twice without delay. One exit gets ignored, then scripting gets into draw() a second time and this time the exit seems to be computed, too. This double call might become visible by the second logfile-excerpt, message-foo ... Removing any additional echo’s and exit’s, the script runs for maximum execution time and then produces the output, Xuefer posted – at modification notifier in ext/session/session.c:OnUpdateSaveHandler. I included some debugging support by calling syslog in zend/zend_ini.c and in session/session.c of PHP's source tree at several points of code. Watching my syslog-file I detected, that my installed session-class didn’t get called for writing and closing, but zend engine shuts down script execution. Well, after detecting one of my variables having values at second run, I've never assigned myself anywhere, I used this to detect the second call and return immediately from method draw() after flushing session with a pair of "session_write_close(); @session_start();". Now there's no execution delay, no strange error message, nothing but a f**king workaround hack. Best Regards Thomas Urban ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at http://bugs.php.net/21306 -- Edit this bug report at http://bugs.php.net/?id=21306&edit=1