php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #47227 children forked with pcntl_fork release flock()s created by parent
Submitted: 2009-01-27 22:07 UTC Modified: 2010-05-21 15:51 UTC
From: murphyk at yahoo-inc dot com Assigned:
Status: Not a bug Package: PCNTL related
PHP Version: 5.2.8 OS: RHEL 4.4
Private report: No CVE-ID: None
 [2009-01-27 22:07 UTC] murphyk at yahoo-inc dot com
Description:
------------
The behavior of flock()ed files across forks appears to have changed between php 4.4.8 and php 5.2.8.

Previously, children would inherit filehandles from their parent, and would close() their copies of the filehandles on exit, but this would not clear flock()s on the files locked in the parent.

Now, it appears that if any child exits(), this will clear flock()s on any filehandles inherited from the parent.

Reproduce code:
---------------
<?php
$fp = fopen("/tmp/lock.txt", "w+");

if (flock($fp, LOCK_EX + LOCK_NB )) {
    print "Got lock.\n";
} else {
    print  "Couldn't lock the file.\n";
    exit();
}
$pid = pcntl_fork();
if ($pid) {
    pcntl_waitpid($pid,$status);
}
else {
    exit();
}
sleep(100);
?>


Expected result:
----------------
$ php flock.php &
[1] 22054
$ Got lock.
$ php flock.php 
Couldn't lock the file.


Actual result:
--------------
$php flock.php &
[1] 31085
$Got lock.
$php flock.php 
Got lock.


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-01-28 08:44 UTC] jani@php.net
RTFM:

man 2 flock
man 2 fork

The behaviour is exactly how it should be and is.

 [2009-01-28 15:13 UTC] murphyk at yahoo-inc dot com
I have RTFM, thanks.

From the man 2 flock:

"Locks  created by flock() are associated with a file, or, more precisely, an open file table entry.  This means that duplicate file descriptors (created by, for  example,  fork(2) or  dup(2)) refer to the same lock, and this lock may be modified or released using any of
these descriptors.  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."

"by an explicit LOCK_UN" - my child process did NOT call flock() in my user code.

"or when all such descriptors have been closed" - my parent process still has an open copy of the the filehandle.

To be clear, the "expected result" output is what happens in php4 - the child closes the filehandle, but doesn't unlock the flock().

php5 appears to be explicitly unlocking all held flocks() during shutdown. If this is intentional, fine, but it's not documented, and it's a change in behavior between php4 and php5 which breaks previously running code.
 [2009-01-29 21:34 UTC] bfrance@php.net
So the problem is the new beefed up streams in 5.x that keeps the lock state for a stream, where it didn't in 4.x.

5.x will unlock it when it cleans up the stream resource if it is locked, look for php_stdiop_close in main/streams/plain_wrapper.c.

4.x would not unlock it and just clean up the handle by closing it, which would leave it locked until the parent closed it or unlocked it.

While this is a bug, I don't think there is any real fix for it that can happen
 [2010-05-21 15:51 UTC] tony2001@php.net
Just to make it clear - this issue has been fixed in revision 292632.
See this diff in trunk: http://svn.php.net/viewvc/php/php-src/trunk/main/streams/plain_wrapper.c?r1=290578&r2=292632
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Tue Oct 08 04:01:28 2024 UTC