|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2009-03-13 10:06 UTC] manuel dot schmitt at manitu dot de
Description: ------------ PHP internal session handler does not correctly closes flock()s on session files Reproduce code: --------------- (This bug seems the same issue as bug #32092) The problem happens on various PHP applications, no matter what they do exactly. Only one same thing: They are all using PHP sessions. In these cases Apache/PHP-processes hanging forever (until killed). I have strace'd the processed, they are hanging on flock()ing the session file as flock(FILE_ID, LOCK_EX, <unfinished>) where FILE_ID is a /tmp/sess_XXX-File (not on NFS, just local) [I have traced this from /proc/PROCID/fd/FILE_ID which links to the session file] I suppose that there was an php process flock()ing the file, perhaps running into max_execution_time, not unflocking the session file correctly and other processed wanting to write session data. Expected result: ---------------- PHP session handler should have some timeout and/or old file locks should be hard-broken. Actual result: -------------- Forever-Hanging php processes. PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Nov 04 21:00:01 2025 UTC |
ARGH! It is so simple! <?php session_start(); while (true) { $i *= 2; } ?> Execute it for the first time and ensure, that it runs into any of the php limits, e.g. maxmimum execution time. Call the script a second time while not running into the limit. When tracing the PHP process you will see an unlimited flock() syscall!Hello, I have the same mistake : host:~# date dimanche 24 octobre 2010, 12:10:03 (UTC+0200) host:~# ps faux | grep php juritrav 17749 0.0 0.0 118988 11616 ? S 00:11 0:00 | \_ /usr/bin/php-cgi suphpuser 17818 0.0 0.0 117764 9536 ? S 00:12 0:00 | \_ /usr/bin/php-cgi suphpuser 18004 0.0 0.0 117764 9536 ? S 00:14 0:00 | \_ /usr/bin/php-cgi suphpuser 12573 0.0 0.1 138812 31784 ? S 09:39 0:00 | \_ /usr/bin/php-cgi suphpuser 12574 0.0 0.0 117492 9396 ? S 09:39 0:00 | \_ /usr/bin/php-cgi duphpuser 12594 0.0 0.0 117492 9396 ? S 09:39 0:00 | \_ /usr/bin/php-cgi suphpuser 12675 0.0 0.0 117764 9536 ? S 09:40 0:00 | \_ /usr/bin/php-cgi suphpuser 12682 0.0 0.0 117764 9536 ? S 09:40 0:00 | \_ /usr/bin/php-cgi suphpuser 12695 0.0 0.0 117764 9536 ? S 09:40 0:00 | \_ /usr/bin/php-cgi So php-cgi scripts run for ever until I kill its manually. I take the sample of process 18004 : front2:~# strace -p18004 Process 18004 attached - interrupt to quit flock(3, LOCK_EX host# lsof -p18004 .... php-cgi 18004 suphpuser 3uW REG 9,1 7 897723 /tmp/php5/sess_xxxxxxxxxxxxxxxxxxxxxxxx (deleted) .... So the php script tries to lock a session file (file descriptor 3) that has been deleted by the PHP garbage collector. When the garbage collector delete a session file, it doesn't take care that any php process still using this session file. Then the php process can't lock the file because it doesn't exist anymore, the php-cgi process is blocked.... I have the problem with the following version of php : PHP 5.2.6-1+lenny9 with Suhosin-Patch 0.9.6.2 (cli) (built: Aug 4 2010 06:06:53) Copyright (c) 1997-2008 The PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies with Zend Optimizer v3.3.9, Copyright (c) 1998-2009, by Zend Technologies The cron job for php (script that delete session on debian) is disabled et the garbage collector php is enabled in php.ini file : session.gc_probability = 1 session.gc_divisor = 100 Sorry for my english. Alexandre LINTEI just encountered this bug on version 5.3.13. The script worked fine for about a year, then stopped working for no known reason (no code changes, version upgrades, etc.) This script works: echo "<br>Flock Test Without Session<br>"; $fp = fopen("_order_id.txt", "r+"); if (flock($fp, LOCK_EX)) { /* do an exclusive lock to get an order number */ $id = fread($fp,filesize("_order_id.txt")); $id++; echo "<br>Got the lock, id is now $id"; ftruncate($fp, 0); /* truncate file */ rewind($fp); /* reset pointer */ fwrite($fp, $id); /* write new order id */ flock($fp, LOCK_UN); /* release the lock */ } else { echo "Couldn't get the lock"; } However, if I put the same code inside a session, it fails on my live site, but still works fine in my localhost (version 5.3.8): session_start(); echo "<br>Flock Test With Session<br>"; $fp = fopen("_order_id.txt", "r+"); if (flock($fp, LOCK_EX)) { /* do an exclusive lock to get an order number */ $id = fread($fp,filesize("_order_id.txt")); $id++; echo "<br>Got the lock, id is now $id"; ftruncate($fp, 0); /* truncate file */ rewind($fp); /* reset pointer */ fwrite($fp, $id); /* write new order id */ flock($fp, LOCK_UN); /* release the lock */ } else { echo "Couldn't get the lock"; } session_destroy();