22

Following this answer to limit only one instance of a php script running:

<?php

  $fp = fopen("/tmp/one.txt", "r+");
  if (flock($fp, LOCK_EX)) {
    //
    do_something_lengthy();
    //
    flock($fp, LOCK_UN);
  } else {
    echo "Couldn't get the lock!";
  }

  fclose($fp);

?>

My question is, will the flock'ed one.txt file be unlock if the process die in the middle of do_something_lengthy(), i.e. before calling flock($fp, LOCK_UN)?

Community
  • 1
  • 1
ohho
  • 50,879
  • 75
  • 256
  • 383
  • This should be easy enough to test. Start something long running, kill it, and see what happens? – Brad Nov 23 '12 at 01:59
  • Yes, of course. If any permanent resource would outlive its host process, that'd be a security hole, since it could be used to DoS the system even as an unprivileged user. – phihag Nov 23 '12 at 02:05

3 Answers3

18

According to the manual page of flock() that PHP uses internally, a lock is released when either flock() is called with LOCK_UN or when the descriptor is closed using fclose().

Upon script termination, either PHP or the OS will close the open file descriptors, thereby releasing the locks you may have.

Because of said behaviour this commit (5.3) and this one (5.2) were made to no longer do the unlocking in PHP itself.

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • According to the `flock()` manual page `fclose()` (which gets run when the script finishes) does not unlock the file since php 5.3.2 – Timo Huovinen Sep 30 '13 at 11:10
  • 1
    Doesn't necessarily mean that the file is not unlocked at the end of the process; I'll run some tests here to see what happens. – Ja͢ck Sep 30 '13 at 12:33
  • I didn't mean that it does not get unlocked, just took bits and pieces from the manual. I did some tests too and indeed it does unlock and fclose at the end of the process – Timo Huovinen Sep 30 '13 at 16:41
  • 1
    @TimoHuovinen I found the commits; in 5.2 the automatic unlock was already being only done for Windows and since 5.3 it was removed altogether :) – Ja͢ck Oct 02 '13 at 02:48
  • How do you know that php uses that given Linux method `flock` internally? Wouldn't it need to use a different method on a windows OS? Does the behavior change in PHP 7? – Adam Dec 15 '17 at 09:17
  • @Adam right ... the question was specific to unix-like systems, and windows _does_ use a different, but comparable, method for locking files – Ja͢ck Dec 15 '17 at 19:40
  • I see, thanks. How can I find out which flock method PHP uses on a certain OS? For example, I would like to know what PHP uses on Ubuntu – Adam Dec 16 '17 at 10:27
  • @Adam afaik, ubuntu is posix compatible, so it would use flock :) – Ja͢ck Dec 16 '17 at 23:36
6

I made this little script to test it out

header('Content-type:text/plain; charset=utf-8');

$dir = dirname(__FILE__);
$file = $dir.'/testflock.lock';
$fh = fopen($file, 'w+');

$unlocked = flock($fh, LOCK_EX | LOCK_NB);
echo 'Locked: '.$file.' ';var_dump(!$unlocked);echo PHP_EOL;
if($unlocked){
    sleep(10);
    throw new Exception();
}

and for me it it took the OS to unlock the file about 2-5 seconds after the script finished executing if it does not throw any Exception, and up to 2-5 seconds after the script stopped because of the thrown Exception.

Keep in mind that as of php 5.3.2 fclose($fh) will not unlock the file, and the file will remain locked unless you unlock it with php or you will have to wait for the OS to unlock it, which might never happen if there is some bug (this happened to me)

To unlock the file:

flock($fh,LOCK_UN);

To close the file handle (will be called automatically when the script finishes executing)

fclose($fh);

Locking the file without the LOCK_NB will cause the script to wait for the file to get unlocked.

Timo Huovinen
  • 53,325
  • 33
  • 152
  • 143
2

The lock is released automatically when the script finishes. However, you should release it manually and not rely on automatic failure to happen. Better to catch any exception, handle it, and release the lock. See the offical docs - http://php.net/manual/en/function.flock.php

Kami
  • 19,134
  • 4
  • 51
  • 63
  • 3
    +1. I've had situations where sometimes the OS did not release the lock – Timo Huovinen Sep 30 '13 at 11:00
  • 2
    Timo - Are you saying that you were able to create situations where the file was locked even when there were no processes running that had an exclusive lock on the file? If so, can you provide an example. – Raghu Dodda May 10 '16 at 17:39
  • I just ran into a situation where my script killed a process with a lock and the lock was not released until I deleted the file. – Jon Hulka Sep 23 '20 at 22:26