Bug #68509 [Ver->Csd]: Garbage collection of file pointers releases flock() locks
Edit report at https://bugs.php.net/bug.php?id=68509&edit=1
ID: 68509
Updated by: git@php.net
Reported by: markamery at btinternet dot com
Summary: Garbage collection of file pointers releases flock()
locks
-Status: Verified
+Status: Closed
Type: Bug
Package: Filesystem function related
Operating System: Unix
PHP Version: master-Git-2014-11-26 (Git)
Assigned To: cmb
Block user comment: N
Private report: N
New Comment:
Automatic comment on behalf of cmb69
Revision: https://github.com/php/doc-en/commit/0bfb0eb957e0468912af86bba09fae588010c1df
Log: Fix #68509: Garbage collection of file pointers releases flock() locks
Previous Comments:
------------------------------------------------------------------------
[2021-07-26 18:21:52] cmb@php.net
man 2 flock[1]:
| Furthermore, the lock is released either by an explicit LOCK_UN
| operation on any of these duplicate descriptors, or when all such
| descriptors have been closed.
That's basically the same on Windows which uses LockFileEx[2]:
| If a process terminates with a portion of a file locked or
| closes a file that has outstanding locks, the locks are unlocked
| by the operating system.
Non-Windows systems which do not support flock(2), basically use
lockf(3)[3]:
| File locks are released as soon as the process holding the locks
| closes some file descriptor for the file.
I have no idea why that "prior to PHP 5.3.2" is there.
[1] <https://linux.die.net/man/2/flock>
[2] <https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-lockfileex>
[3] <https://linux.die.net/man/3/lockf>
------------------------------------------------------------------------
[2016-08-26 13:34:11] cmb@php.net
I can confirm the behavior (mode "w" might not necessarily work,
but I also get the behavior with "c" and "r") on Windows.
------------------------------------------------------------------------
[2014-11-26 21:17:12] markamery at btinternet dot com
Description:
------------
If you acquire a file pointer with fopen() from within a function, then take out a lock on it with
flock(), the lock gets released when the function returns unless you keep a reference to the file
pointer in scope to prevent it from being garbage collected.
This seems wrong on two counts:
* It's unintuitive to the user that implicit garbage collection could be affecting their locks;
the user should be protected from such concerns. In any case, this interaction between garbage
collection and locks is undocumented.
* It appears to contradict the documentation at http://php.net/manual/en/function.flock.php
which claims that:
> The automatic unlocking when the file's resource handle is closed was removed.
> Unlocking now always has to be done manually.
In fact, it is the case that both explicit fclose() calls and the file pointer being garbage
collected result in the lock being released, contrary to the documentation.
This should probably be fixed by tracking whether a file pointer has been locked with flock(), and
suppressing the garbage collection of file pointers for which there are active flock() locks.
Related: I have previously posted a question and answer on Stack Overflow about this issue: http://stackoverflow.com/questions/24351769/flock-call-within-function-always-succeeds-ignoring-previous-lock
Test script:
---------------
<?php
function acquire_lock () {
$file_handle = fopen('mylock.lock', 'w');
$got_lock_successfully = flock($file_handle, LOCK_EX);
if (!$got_lock_successfully) {
throw new Exception("Unexpected failure to acquire lock.");
}
}
acquire_lock();
echo "Acquired lock\n";
sleep(10);
echo "terminating\n";
?>
Expected result:
----------------
When starting the test script above in two terminals in rapid succession, the second terminal should
not display the "Acquired lock" message until the first terminal has shown the
"terminating" message.
Actual result:
--------------
The second terminal shows the "Acquired lock" message as soon as the script is started,
before the first script has shown the "terminating" message.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=68509&edit=1
Thread (4 messages)