Each call of flock on the same file handler, firstly releases the lock and then tries to acquire it again.
<?php
$f = fopen('/tmp/file.lock', 'c');
var_dump(flock($f, LOCK_EX)); // outputs true
var_dump(flock($f, LOCK_EX)); // outputs true
var_dump(flock($f, LOCK_SH)); // outputs true
fclose($f);
Assigning another value to handle argument in subsequent code will release the lock.
So for the same file handler (in one threaded application) each flock call will always return true. Locking mechanism is designed for running multiple processes at once, or if you open multiple file handlers to file.
<?php
$f1 = fopen('/tmp/file.lock', 'c');
$f2 = fopen('/tmp/file.lock', 'c');
var_dump(flock($f1, LOCK_EX | LOCK_NB)); // outputs true
var_dump(flock($f2, LOCK_EX | LOCK_NB)); // outputs false
var_dump(flock($f2, LOCK_SH | LOCK_NB)); // outputs false
fclose($f1);
fclose($f2);
Below is a test program which will show differences between real file locking and locking mechanism in vfsStream.
<?php
require_once('vendor/autoload.php');
use org\bovigo\vfs;
function testFlockLock($handle, $lock) {
$output = array();
$output[] = $handle;
$output[] = $lock & LOCK_EX ? "LOCK_EX" : "LOCK_SH";
$output[] = flock($handle, $lock | LOCK_NB) ? "success" : "fail";
echo join(' ', $output)."\n";
}
function testFlockUnlock($handle) {
$output[] = $handle;
$output[] = "LOCK_UN";
$output[] = flock($handle, LOCK_UN) ? "success" : "fail";
echo join(' ', $output)."\n";
}
vfs\vfsStream::setup('tmp');
$files = array();
$files[] = '/tmp/file.lock';
$files[] = vfs\vfsStream::url('tmp/file.flock');
foreach ($files as $file) {
$handle1 = fopen($file, 'c');
$handle2 = fopen($file, 'c');
echo $file."\n";
testFlockLock($handle1, LOCK_SH);
testFlockLock($handle1, LOCK_SH);
testFlockLock($handle1, LOCK_EX);
testFlockLock($handle1, LOCK_EX);
testFlockLock($handle1, LOCK_SH);
testFlockUnlock($handle1);
testFlockLock($handle1, LOCK_EX);
testFlockLock($handle1, LOCK_EX);
echo "\n";
testFlockLock($handle2, LOCK_EX);
testFlockLock($handle2, LOCK_SH);
testFlockLock($handle2, LOCK_EX);
echo "\n";
testFlockUnlock($handle1);
testFlockUnlock($handle2, LOCK_UN);
testFlockLock($handle1, LOCK_SH);
testFlockLock($handle2, LOCK_SH);
testFlockLock($handle2, LOCK_EX);
testFlockUnlock($handle1);
testFlockUnlock($handle2);
testFlockLock($handle1, LOCK_EX);
testFlockLock($handle2, LOCK_SH);
echo "\n";
}
/tmp/file.lock
Resource id #18 LOCK_SH success
Resource id #18 LOCK_SH success
Resource id #18 LOCK_EX success
Resource id #18 LOCK_EX success
Resource id #18 LOCK_SH success
Resource id #18 LOCK_UN success
Resource id #18 LOCK_EX success
Resource id #18 LOCK_EX success
Resource id #19 LOCK_EX fail
Resource id #19 LOCK_SH fail
Resource id #19 LOCK_EX fail
Resource id #18 LOCK_UN success
Resource id #19 LOCK_UN success
Resource id #18 LOCK_SH success
Resource id #19 LOCK_SH success
Resource id #19 LOCK_EX fail
Resource id #18 LOCK_UN success
Resource id #19 LOCK_UN success
Resource id #18 LOCK_EX success
Resource id #19 LOCK_SH fail
vfs://tmp/file.flock
Resource id #21 LOCK_SH success
Resource id #21 LOCK_SH success
Resource id #21 LOCK_EX fail
Resource id #21 LOCK_EX fail
Resource id #21 LOCK_SH success
Resource id #21 LOCK_UN success
Resource id #21 LOCK_EX success
Resource id #21 LOCK_EX fail
Resource id #22 LOCK_EX fail
Resource id #22 LOCK_SH fail
Resource id #22 LOCK_EX fail
Resource id #21 LOCK_UN success
Resource id #22 LOCK_UN success
Resource id #21 LOCK_SH success
Resource id #22 LOCK_SH success
Resource id #22 LOCK_EX fail
Resource id #21 LOCK_UN success
Resource id #22 LOCK_UN success
Resource id #21 LOCK_EX success
Resource id #22 LOCK_SH fail
I'm currently finishing my proposition how to implement flock in vfsStream. I will push this soon.