Edit report at https://bugs.php.net/bug.php?id=63709&edit=1
ID: 63709
Updated by: laruence@php.net
Reported by: eric dot saintetienne at gmail dot com
Summary: flock() doesn't trigger mandatory locks on linux
Status: Analyzed
Type: Bug
Package: Filesystem function related
Operating System: Linux
PHP Version: 5.3.19
Block user comment: N
Private report: N
New Comment:
I like 3 :)
change the behavior of flock will intruduce a visible bc break
Previous Comments:
------------------------------------------------------------------------
[2012-12-07 01:48:08] aharvey@php.net
The key difference between Python and PHP here is that Python always uses fcntl() internally,
whereas PHP will use flock() if it's available (which it obviously is on Linux) and will only
fall back to fcntl() if it's not. flock() will never create a mandatory lock, so the manual
page is wrong, which I'm pretty sure is my fault. Mea culpa.
We can probably fix this by switching to preferring fcntl() within our flock() function as Python
does, since that's actually the more useful behaviour, but that would be a (mild) BC break in
how flock() behaves in practice â although it would actually bring it into line with
what's documented.
The options I see are:
1. Change the behaviour of flock() as described above to prefer fcntl().
2. Add a new lockf() function, as suggested.
3. Just bite the bullet and expose fcntl() as a PHP function on POSIX platforms.
4. Do nothing and update the manual. :)
Does anyone have any thoughts? I'm happy to do the donkey work, but am not really sure on the
best way to proceed.
------------------------------------------------------------------------
[2012-12-06 14:19:38] eric dot saintetienne at gmail dot com
Note that dio_fcntl() of the "Direct IO" extension can successfully exclusively
lock the file, but this shouldn't be considered as a workaround as it's not always
possible to install extensions.
If flock() couldn't be modified for backward compatibility reasons, options could
be added to alter its behaviour, or a new call lockf() would be welcome too.
------------------------------------------------------------------------
[2012-12-06 13:12:43] eric dot saintetienne at gmail dot com
Description:
------------
Locking exclusively via flock a file opened for writing doesn't trigger a
mandatory lock.
The python script below could trigger the mandatory lock.
Maybe it's because PHP flock() is built on the C function call flock():
"When a program attempts to lock a file with lockf or fcntl that has mandatory
locking set, the kernel will prevent all other programs from accessing the file.
Processes which use flock will not trigger a mandatory lock."
source: http://www.hackinglinuxexposed.com/articles/20030623.html
Python script:
#!/usr/bin/python
import os, fcntl
fd = os.open('mandlock-file', os.O_RDWR, 0755)
print 'fd=', fd
fcntl.lockf(fd, fcntl.LOCK_EX)
a = raw_input() # during that time, any attempt to open the file will hang
os.write(fd, a+'\n')
fcntl.lockf(fd, fcntl.LOCK_UN)
# now any attempt to open the file will succeed
os.close(fd)
# eof
Test script:
---------------
<?php
define('FILENAME', 'mandlock-file');
/* first create a file with a mandatory lock:
* $ touch mandlock-file
* $ chmod g+s,g-x mandlock-file
* $ sudo mount -o remount,mand / # my file is inside the '/' mountpoint
*/
function openlockedfile($filename) {
$fp = fopen($filename, 'w+');
while (($fp === false) || (flock($fp, LOCK_EX) !== true)) {
sleep(1);
echo "spin lock\n";
if ($fp === false)
$fp = fopen($filename, 'w+');
}
return $fp;
}
$fd = openlockedfile(FILENAME); // open + lock EX
sleep(10);
/* During this sleep time, accessing the file should hang until the
* php script releases the exclusive lock:
* $ cat mandlock-file # should hang until php script termination
* Practically, cat doesn't hang (and works) proving the file isn't
* exclusively locked by the PHP script. */
closefile($fd); // unlock + close
/* eof */
?>
Expected result:
----------------
once the file is created and the mandatory lock setup for it:
during the 10 sec timer, opening the file (with or without explicit locking)
should hand until the php script terminates.
Actual result:
--------------
it's possible to opening the locked file during the 10s timer for reading and
writing.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=63709&edit=1