#31363 [Fbk->Opn]: Non-blocking flock() broken

From: Date: Tue, 05 Apr 2005 15:59:12 +0000
Subject: #31363 [Fbk->Opn]: Non-blocking flock() broken
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-76395@lists.php.net to get a copy of this message
ID: 31363 User updated by: ian at snork dot net Reported By: ian at snork dot net -Status: Feedback +Status: Open Bug Type: Filesystem function related Operating System: Debian woody (i386) PHP Version: 5CVS-2005-03-09 New Comment: Aw, shucks. It's been word-wrapped. Oh well -- send mail if you need an unmolested copy of the patch. :) Previous Comments: ------------------------------------------------------------------------ [2005-04-05 17:57:55] tony2001@php.net Please, generate diffs with diff -upd and put them somewhere in the Net. Thanks you. ------------------------------------------------------------------------ [2005-04-05 17:53:57] ian at snork dot net The cause looks to be two separate bugs; here's a patch to fix both. *** php5-200504050030.orig/ext/standard/file.c Sun Mar 27 16:30:05 2005 --- php5-200504050030/ext/standard/file.c Tue Apr 5 15:26:08 2005 *************** *** 339,351 **** /* flock_values contains all possible actions if (operation & 4) we won't block on the lock */ act = flock_values[act - 1] | (operation & 4 ? LOCK_NB : 0); ! if (!php_stream_lock(stream, act)) { if (operation && errno == EWOULDBLOCK && arg3 && PZVAL_IS_REF(arg3)) { Z_LVAL_P(arg3) = 1; } ! RETURN_TRUE; } ! RETURN_FALSE; } /* }}} */ --- 339,351 ---- /* flock_values contains all possible actions if (operation & 4) we won't block on the lock */ act = flock_values[act - 1] | (operation & 4 ? LOCK_NB : 0); ! if (php_stream_lock(stream, act)) { if (operation && errno == EWOULDBLOCK && arg3 && PZVAL_IS_REF(arg3)) { Z_LVAL_P(arg3) = 1; } ! RETURN_FALSE; } ! RETURN_TRUE; } /* }}} */ *** php5-200504050030.orig/main/streams/plain_wrapper.c Thu Oct 28 06:35:19 2004 --- php5-200504050030/main/streams/plain_wrapper.c Tue Apr 5 15:45:51 2005 *************** *** 578,584 **** return 0; } ! if (!flock(fd, value) || (errno == EWOULDBLOCK && value & LOCK_NB)) { data->lock_flag = value; return 0; } else { --- 578,584 ---- return 0; } ! if (!flock(fd, value)) { data->lock_flag = value; return 0; } else { ------------------------------------------------------------------------ [2005-04-05 01:55:32] maurice at gitaar dot net I had the same problem. It seems that errno is not reset to zero in the flock implementation. Therefore the last errno will be used. In case no other errno-modifying call is made before retrying the flock() call, the call will conclude in an EWOULDBLOCK situation (my conclusion after a very quick scan of the code). Looking with truss on Solaris to the process shows that the first fcntl call (during which I have already locked the file) returns an EAGAIN error, meaning that the file was already locked. The second fnctl call (on the now unlocked file) does not return an error. So the call is successfull. But the call from the php code does set the $wouldblock parameter to a true value. For me a workaround for now is something like this (no error checking on flock and a bit of pseudo-coded, but the workaround is the important part): for (;;) { flock($fd, LOCK_EX|LOCK_NB, $wouldblock); if (! $wouldblock) break; fopen("/this/is/no/real/file", "r"); } The fopen() call sets errno to the file not found error, which makes the flock() call act like the first time it is called. This is not great coding, but it does work for me till a real fix is implemented in PHP. ------------------------------------------------------------------------ [2005-04-01 14:42:19] maka3d at yahoo dot com dot br I expected it to be fixed until 5.0.4. On freeBSD it doesn't work too :( ------------------------------------------------------------------------ [2005-03-09 17:29:56] ian at snork dot net flock() in today's PHP CVS snapshot (http://snaps.php.net/php5-latest.tar.bz2) behaves slightly differently, but still doesn't quite work correctly in non-blocking mode. Expected result: -------------- $ php5 flock_test.php & Got /tmp/test1 $ php5 flock_test.php & Got /tmp/test2 $ php5 flock_test.php & Got /tmp/test3 $ php5 flock_test.php & $ Releasing /tmp/test1 Got /tmp/test1 Releasing /tmp/test2 Releasing /tmp/test3 Actual result: -------------- $ php5 flock_test.php & Got /tmp/test1 $ php5 flock_test.php & Got /tmp/test2 $ php5 flock_test.php & Got /tmp/test3 $ php5 flock_test.php & $ Releasing /tmp/test1 Releasing /tmp/test2 Releasing /tmp/test3 ------------------------------------------------------------------------ The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at http://bugs.php.net/31363 -- Edit this bug report at http://bugs.php.net/?id=31363&edit=1

« previous php.bugs (#76395) next »